初涉多线程
来源:互联网 发布:中国根域名服务器 镜像 编辑:程序博客网 时间:2024/05/02 04:24
1. 什么是线程
直接调用run()方法,不会建立新线程,只有调用start()方法才能开启新线程.
当前线程调用sleep()或wait()方法,让线程处以空闲状态.给其他线程机会完成它们的运行,但大部分操作系统都有自己调度线程的方法.即使两个利己线程,都有机会得到CPU的资源.
如果一个类需要新线程运行,那它可以继承Thread类,并覆盖run()方法.如果该类已有超类.那么可以实现Runnable接口.如果线程的run()方法需要专门访问一个类,那更好的方法是使用内部类.
2. 线程的中断
interrupted() 静态方法 返回线程的中断状态,并将中断状态设为false
isInterrupte() 实例方法 仅返回线程的中断状态
interrupte() 将线程的中断状态设为true 仅改变线程interrupt标志
单一个线程处以sleep()或wait()方法时,被其他线程调用了该线程的interrupt 方法.这两个方法会抛出InterruptedException 异常.通过捕获这个异常可以结束线程的运行.如果仅对sleep()或wait()方法进行捕获.线程还可以继续运行.同时interrupt又被设置为false
即使调用t.interrupte().线程仍继续运行.并且输入恒为false
3. 线程的属性
线程有4种状态
new(新)
但调用new 运算符创建一个线程时,该线程尚未运行.这时线程便处以new 状态
runnable(可运行)
当调用start方法时,线程便处于可运行状态.可运行并不是说正在运行.需要操作系统为该线程赋予运行的时间
一些操作系统(windows)能够为每个可运行的线程赋予一个时间片,以便执行它的任务.当该时间片用完时,操作系统便为另一个线程提供运行的机会.这种方法称为时间分片(time slicing)
blocked(被中断运行)
当出现下列操作,线程便进入中断状态
调用了该线程的sleep()方法
该线程调用了一个I/O时中断的操作.
该线程调用了wait()方法;
该线程试图锁定一个被另一个线程锁定的对象
调用了该线程的suspend()方法,该方法已作废.
相应的退出中断状态
线程的睡眠经过了规定的毫秒数
I/O操作完成
调用wait()方法等待的线程.其他线程调用了notify()或notifyAll()方法
线程等待锁时,另一个线程放弃了该锁
如果调用了该线程的suspend()方法,那调用该线程的resume()方法就退出中断.同样已废
dead(死)
run方法自然退出,此时线程自然死亡
由于异常未捕获而导致run方法终止,会导致线程突然死亡
调用stop()方法可杀死线程.该方法以作废
java守护线程:
一种特殊的线程,从属于创建它的线程.主要应用于程序的非核心处理部分.比如word文档中用来监听输入的是非守护线程.用来检查拼写的是可以守护线程.
如果上面的线程是非守护线程的活.jvm需要等到 线程死亡才 结束运行,如果是守护线程则直接结束运行
做游戏中的背景音乐可以考虑用守护线程来做.
线程组
是一种树结构
4. 线程的优先级
在java中,每个线程都有一个优先级.优先级的取值可以为1(MIN_PRIORITY)~10 (MAX_PRIORITY).在默认情况下,一个线程将继承其父线程的优先级
当线程调度程序有机会选择一个新线程时,它通常会选择当前处于可运行状态下的高优先级线程.如果有多个高优先级线程.无法控制调度程序去选定一个特定的线程.一般调度程序会随机选择一个线程.
yield()静态方法 使当前线程放弃运行.如果有其他可运行线程的优先级至少与当前线程相同.那么它们将被安排在下次运行
5. 利己线程
当某个线程执行一个很长的循环时,它应该始终调用sleep()或yield()方法.以确保它不会独占整个系统.不遵循这个原则的线程称为利己线程
如果程序在windows或者在本机线程机制下运行,那么利己线程不会独占整个系统
6. 同步
假设有两条线程,同时执行value+=random;在两条线程中value是内存中的同一位置,比如.既是同一对象的同一属性.random是不同的随机值.线程执行的操作是 将value装入寄存器.并将random相加.再将结果重新移到value.
如果此时value=1000,线程一的random=200,线程2的random=300;当线程1执行了将1000装入寄存器.并将random相加.此时线程1中的寄存器的值为1200.系统到这时刚好把线程1的运行中断了.并唤醒了线程2. 线程2将1000装入寄存器.并将random相加.此时线程2中的寄存器的值为1300,并将结果赋给了value.接着线程1被唤醒了.它执行了将寄存器中的值1200赋给了value的操作.该操作破坏了线程2进行的修改.程序运行的正确性就被破坏了.
每个线程可以同时对同一个对象的属性进行修改.就破坏了类的完整性.这就是异步的危险.
synchronized
当一个线程调用了synchronized方法时.在synchronized方法结束之前.其他线程再也无法执行同一对象中的synchronized方法.
对象锁
实际上当线程调用了sychronized方法是.便将对象转为”锁定”状态.处于”锁定”状态的对象.其他线程只能访问该对象的unsynchronized方法.若调用了synchronized方法.就等待该对象的锁被打开.当线程退出了它的synchronized方法时,便打开了对象的锁
wait和notify
wait和notify notifyAll 都是Object类的方法.
当调用wait方法是对象便打开自己的锁.并且中断当前线程的运行.当前线程进入等待列表
notify:从对象的等待列表中删除一个任意选择的线程
notifyAll:将对象等待列表中的所有线程全部删除.
从等待列表删除线程.并不会立刻激活该线程.只能撤销等待线程的中断状态.与其他线程展开竞争
同步块
同步静态方法
如果一个线程调用了一个类的静态synchronized方法,那么这个类其他的静态synchronized方法都会被锁定.直到静态synchronized方法返回.
7. 死锁
如果其他所有线程都被wait()锁定,并且最后一个活动线程在不打开其他线程的锁的情况下,调用wait(),这种情况叫做死锁.
废除stop和suspend方法
stop()不会使对象永久性锁定,但会使对象受损.(方法执行不完整)
当一个线程拥有对象锁时,被调用suspend不会解除锁.那其他挂起的线程要等待该对象撤销锁定.便形成了死锁.
超时
wait(long millis) wait(long millis,int nanos)
如果线程调用以上方法进行等待.那么在规定时间到后,线程还没被notifyAll/notify唤醒时,线程将自动唤醒.
- 初涉多线程
- 初涉多线程
- 初涉多线程与socket
- 初尝多线程
- 多线程之初理解
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- ORACLE的锁
- 努力工作!努力赚钱!
- iis 绑定命令
- linux CVS配置(这篇也很不错)
- wrapper类注意
- 初涉多线程
- _stdcall 与 _cdecl 的区别
- COM,魔鬼的艺术
- [转]Writing An Hadoop MapReduce Program In Python
- 使用Python操作注册表
- 嵌入式Linux文件系统及其存储机制分析
- 要成为一名考古学者要具备什么
- 浅谈C#托管程序中的资源释放问题
- gridview