2、wait() 使当前线程阻塞,前提是必须先获得锁,一般配合synchronized 关键字使用 。
即 , 一般在 synchronized 同步代码块里使用 wait()、notify、notifyAll() 方法 。
3、由于 wait()、notify()、notifyAll() 方法在 synchronized 代码块执行,说明当前线程一定是获取了锁的 。当线程执行wait()方法时候 , 会释放当前的锁,然后让出CPU,进入等待状态 。只有当 notify()/notifyAll() 被执行时候 , 才会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完 synchronized 代码块的代码或是中途遇到wait() , 再次释放锁 。也就是说,notify()/notifyAll() 的执行只是唤醒沉睡的线程,而不会立即释放锁 , 锁的释放要看代码块的具体执行情况 。所以在编程中,尽量在使用了 notify()/notifyAll() 后立即退出临界区,以唤醒其他线程让其获得锁 。
4、notify 和 wait 的顺序不能错 , 如果A线程先执行notify方法,B线程在执行wait方法,那么B线程是无法被唤醒的 。
5、notify 和 notifyAll的区别:
- notify: 只唤醒一个等待(对象的)线程并使该线程开始执行 。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现 。
- notifyAll: 会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现 。如果当前情况下有多个线程需要被唤醒,推荐使用notifyAll方法 。
package cn.itcast.thread;import java.util.concurrent.TimeUnit;/** * 测试 wait()、notify()、notifyAll() */public class Test1 { public static void main(String[] args) { // 创建对象 Object obj = new Object(); // 线程t1 new Thread(() -> { synchronized (obj) { try { System.out.println(Thread.currentThread().getName() + "wait 前"); obj.wait(); // 等待、线程阻塞(释放锁) System.out.println(Thread.currentThread().getName() + "wait 后"); } catch (InterruptedException e) { e.printStackTrace(); } } }, "t1:").start(); // 线程t2 new Thread(() -> { synchronized (obj) { try { System.out.println(Thread.currentThread().getName() + "wait 前"); obj.wait(); // 等待、线程阻塞(释放锁) System.out.println(Thread.currentThread().getName() + "wait 后"); } catch (InterruptedException e) { e.printStackTrace(); } } }, "t2:").start(); // 线程t3 new Thread(() -> { synchronized (obj) { try { // 休眠2秒 TimeUnit.SECONDS.sleep(2); //目的让前2个线程进入等待状态 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("notifyAll 前"); obj.notifyAll(); // 唤醒全部等待的线程,不会释放锁 System.out.println("notifyAll 后"); } }, "t3:").start(); }
小结- wait()方法的作用?
- notify()方法的作用?
线程状态
线程可以处于以下状态之一:
- NEW 尚未启动的线程处于此状态 。
- RUNNABLE 在Java虚拟机中执行的线程处于此状态 。
- BLOCKED 被阻塞等待的线程处于此状态 。
- WAITING 无限等待另一个线程执行特定动作的线程处于此状态 。
- TIMED_WAITING 一个正在限时等待另一个线程执行一个动作的线程处于这一状态 。
- TERMINATED 已退出的线程处于此状态 。
状态转换
文章插图
代码:
package cn.itcast.thread;/** 测试: 线程6种状态 */public class Test2 { // 方法1 (RUNNABLE: 运行) public static void test1() { new Thread(() -> { synchronized (Test2.class) { while (true) { } } }, "t1-runnable").start(); //线程运行中 } // 方法2 (TIMED_WAITING : 超时等待) public static void test2() { new Thread(() -> { synchronized (Test2.class) { while (true) { try { Test2.class.wait(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "t2-timed_waiting").start(); //线程超时等待中 } // 方法3 public static void test3() { // (RUNNABLE: 运行) new Thread(() -> { synchronized (Test2.class) { while (true) { } } }, "t3-runnable").start(); // (BLOCKED: 阻塞) new Thread(() -> { synchronized (Test2.class) { //由于上面没有释放锁,被阻塞中 } }, "t4-BLOCKED").start(); } // 方法4 (WAITING : 等待) public static void test4() { new Thread(() -> { synchronized (Test2.class) { while (true) { try { Test2.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "t5-waiting").start(); //线程等待中 } public static void main(String[] args) { //test1(); // 线程运行中 //test2(); // 线程超时等待中 test3(); // 线程阻塞中 //test4(); // 线程等待中 }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- “正科级”公务员退休后有多少钱?40年工龄的话,预计是这个数
- 女人对你有好感,哪怕嘴上不说,这7个肢体语言也藏不住
- “无性婚姻”有多可怕?听听3个过来人的故事,希望你能引以为戒
- 家里放了几年的红茶、绿茶、普洱茶,还能喝吗?医生告诉你实话
- 求求你们别再换脸了,就像好好的一盘菜吃出苍蝇的感觉!
- 拒认儿子巴图20年,晚年态度翻转,是居心叵测,还是真后悔?
- 教你自己制作花生酱,教你自制花生酱
- 微博该咋得才可以删除评论,为什么微博评论删除后还有显示
- 《我知道我爱你》热播:和冬天适配的偶像剧
- 李善均离世早有端倪?留下遗书后离家,现场有点燃闪电弹的痕迹