wait()、sleep()、notify()、notifyAll()、interrupt()、join()、yield() 、interrupted()所属类及其作用分析
来源:互联网 发布:上海政府数据开放平台 编辑:程序博客网 时间:2024/06/07 01:36
参考资源:
http://blog.csdn.net/zyplus/article/details/6672775
notify()、notifyAll()、wait()属于java.lang.Object,java.lang.Thread也是Object,自然也有上述方法;
sleep()、interrupt()、interrupted()、join()、yield()属于java.lang.Thread
wait()方法表示,放弃当前对资源的占有权,等啊等啊,一直等到有人通知我,我才会运行后面的代码。
notify()方法表示,当前的线程已经放弃对资源的占有,通知等待的线程来获得对资源的占有权,但是只有一个线程能够从wait状态中恢复,然后继续运行wait()后面的语句;
notifyAll()方法表示,当前的线程已经放弃对资源的占有,通知所有的等待线程从wait()方法后的语句开始运行。
Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
单单在概念上理解清楚了还不够,需要在实际的例子中进行测试才能更好的理解。对Object.wait(),Object.notify()的应用最经典的例子,应该是三线程打印ABC的问题了吧,这是一道比较经典的面试题,题目要求如下:
建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。代码如下:
<span style="font-size:14px;">package thread;public class MyThreadPrinterABC implements Runnable {private String name;private Object prev;private Object self;private MyThreadPrinterABC(String name, Object prev, Object self) {this.name = name;this.prev = prev;this.self = self;}@Overridepublic void run() {int count = 10;while (count > 0) {synchronized (prev) {synchronized (self) {System.out.print(name);count--;self.notify();}try {if (count > 0)prev.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) throws Exception {Object a = new Object();Object b = new Object();Object c = new Object();MyThreadPrinterABC pa = new MyThreadPrinterABC("A", c, a);MyThreadPrinterABC pb = new MyThreadPrinterABC("B", a, b);MyThreadPrinterABC pc = new MyThreadPrinterABC("C", b, c);new Thread(pa).start();Thread.sleep(1);new Thread(pb).start();Thread.sleep(1);new Thread(pc).start();Thread.sleep(1);}}</span>
下面继续说sleep()、join()、yield()
sleep()使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。
例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。
总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
join()方法使调用该方法的线程在此之前执行完毕,也就是等待该方法的线程执行完毕后再往下继续执行。注意该方法也需要捕捉异常。
yield()方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
A.join,在API中的解释是,堵塞当前线程B,直到A执行完毕并死掉,再执行B;A.yield,A让出位置,给B执行,B执行结束A再执行。跟join意思正好相反!sleep 方法使当前运行中的线程睡眠一段时间,进入不可以运行状态,这段时间的长短是由程序设定的,yield方法使当前线程让出CPU占有权,但让出的时间是不可设定的。
yield()也不会释放锁标志。
实际上,yield()方法对应了如下操作;先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把CPU的占有权交给次线程,否则继续运行原来的线程,所以yield()方法称为“退让”,它把运行机会让给了同等级的其他线程。
sleep 方法允许较低优先级的线程获得运行机会,但yield()方法执行时,当前线程仍处在可运行状态,所以不可能让出较低优先级的线程此时获取CPU占有权。在一个运行系统中,如果较高优先级的线程没有调用sleep方法,也没有受到I/O阻塞,那么较低优先级线程只能等待所有较高优先级的线程运行结束,方可有机会运行。
yield()只是使当前线程重新回到可执行状态,所有执行yield()的线程有可能在进入到可执行状态后马上又被执行,所以yield()方法只能使同优先级的线程有执行的机会。
最后说一下interrupt和interrupted,直接看例子:
package thread;public class TestInterrupt implements Runnable {int i = 10;@Overridepublic void run() {while (i-- > 0) {System.out.println("I am running!");try {Thread.sleep(100);} catch (InterruptedException e) {System.out.println("--------- InterruptedException ----------");continue;}}}public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new TestInterrupt());t.start();Thread.sleep(500);// 运行一断时间后中断线程System.out.println("****************************");System.out.println("Interrupted Thread!");System.out.println("****************************");t.interrupt();//你以为到这里会中断吗?}}
你以为线程运行到t.interrupt();就会中断吗?看看结果:
I am running!I am running!I am running!I am running!I am running!I am running!****************************Interrupted Thread!****************************--------- InterruptedException ----------I am running!I am running!I am running!I am running!
虽然中断发生了,但线程仍然在进行,离开线程有两种常用的方法:
抛出InterruptedException和用Thread.interrupted()检查是否发生中断,下面分别看一下这两种方法:
1.在阻塞操作时如Thread.sleep()时被中断会抛出InterruptedException(注意,进行不能中断的IO操作而阻塞和要获得对象的锁调用对象的synchronized方法而阻塞时不会抛出InterruptedException),代码如下:
public void run() { //死循环执行打印"I am running!" try { while (true) { System.out.println("I am running!"); //休眠一断时间,中断时会抛出InterruptedException Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("TestInterrupt.run() interrupted!"); } }
2.Thread.interrupted()检查是否发生中断.Thread.interrupted()能告诉你线程是否发生中断,并将清除中断状态标记,所以程序不会两次通知你线程发生了中断.代码如下:
public void run() { //检查程序是否发生中断 while (!Thread.interrupted()) { System.out.println("I am running!"); } System.out.println("TestInterrupt.run() interrupted!"); }
- wait()、sleep()、notify()、notifyAll()、interrupt()、join()、yield() 、interrupted()所属类及其作用分析
- 深入剖析Sleep、wait、notify、notifyAll、yield、join、Interrupt
- sleep,yield,join,notify,wait,notifyAll区别
- wait、notify、notifyAll、sleep、join、yield
- Java多线程-wait(), notify(), notifyAll()、yield()、sleep()、join()、interrupt()原理及使用
- java中interrupt、join、sleep、notify、notifyAll、wait详解
- java中interrupt、join、sleep、notify、notifyAll、wait详解
- sleep、join、yield、wait、notify、notifyAll、run、start、synchronized
- java sleep() join() yield() wait()和notify()、notifyAll() 区别详解
- java Thread sleep yield join wait notify notifyAll
- java 线程:sleep join yield | wait notify notifyAll
- java notify()、 notifyAll()、 wait()、sleep()、yield()、join()方法学习
- 线程sleep、wait、yield、join、notify、notifyAll 以及queue
- java线程sleep join yield wait notify notifyAll
- sleep、join、yield、notify、notifyall
- java 线程的状态分析 sleep yield join wait notify notifyall
- Java线程中sleep()、wait()和notify()和notifyAll()、suspend和resume()、yield()、join()、interrupt()的用法和区别
- Java线程中sleep()、wait()和notify()和notifyAll()、suspend和resume()、yield()、join()、interrupt()的用法和区别
- Android WebView缓存机制
- Libevent源码分析-----Libevent时间管理
- HDU--1195:Open the Lock (一道简单的BFS)
- shell脚本定时任务 ( linux系统)
- 8大排序算法图文讲解
- wait()、sleep()、notify()、notifyAll()、interrupt()、join()、yield() 、interrupted()所属类及其作用分析
- poj 1066
- __weak如何实现对象值自动设置为nil的
- 程序员也要不停学习不停总结
- Eclipse快捷键大全
- Windows sockets网络开发-基本UDP套接字编程
- Mybatis运作流程(手动方式创建sqlSessionFactory)
- Oracle中的Join(连接)的使用
- C++及OpenCV中调用Tesseract