-
2021-09-17 09:31:45
1 synchronized
等待 wait 唤醒 notify唤醒 还有一个 notifyAll 唤醒全部
2 ReenTrantLock
lock.newCondition
await() 等待
singal() 唤醒
上面两个等待和唤醒有一个问题 是就是 要求顺序性和 必须加锁 比如 第一个线程 没有锁第二个线程也可以使用唤醒方法还不会抛出异常 但是 问题是 在运行编译的时候会报错 同时 在 等待和唤醒的顺序上也不能 搞混 如果 唤醒 先于等待 执行也会抛出异常
3 LockSupport
这里有 park() unpark() 线程阻塞 和 释放 这里没有这个问题 但是他们是成双成对出险 如果释放线程先于执行 那么后续在一个线程内部的park()的阻塞通通不生效 这个东西 在独立的线程内部只是第一个生效 如果 连续阻塞 只要有 有另一个线程释放了 所有阻塞都失效了 所以根据情况而定使用哪种方式
这个 好处是 不会有异常 切不要求顺序 根据情况而定Thread thread = new Thread(() -> { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("1"); LockSupport.park(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //这个不会生效 只要有释放他也会被置于 释放状态 LockSupport.park(); System.out.println("2"); }, "a"); Thread threadw = new Thread(() -> { System.out.println("5"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } LockSupport.park(); System.out.println("6"); }, "b"); threadw.start(); Thread thread2 = new Thread(() -> { System.out.println("3"); LockSupport.unpark(thread); System.out.println("4"); }, "c"); thread2.start(); thread.start();
更多相关内容 -
让线程等待和唤醒的3种方式
2020-05-25 10:27:06使用Object package study; public class Test { public static void main(String[] args) throws InterruptedException { ... System.out.println("进入线程t1"); synchronized (lock) { System.out.pr使用Object
package study; public class Test { public static void main(String[] args) throws InterruptedException { Object lock = new Object(); Thread t1 = new Thread(() -> { System.out.println("进入线程t1"); synchronized (lock) { System.out.println("线程t1准备进入等待状态"); try { lock.wait(); } catch (Exception e) { e.printStackTrace(); } } System.out.println("线程t1撤出了"); }); t1.start(); Thread.sleep(1000); System.out.println("主线程休眠完毕,准备唤醒t1线程"); synchronized (lock) { lock.notify(); } } }
使用Condition
package study; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Test1 { static ReentrantLock lock = new ReentrantLock(); static Condition condition = lock.newCondition(); public static void main(String[] args) { Thread t1 = new Thread(() -> { lock.lock(); System.out.println("线程t1开始执行"); try { try { System.out.println("线程t1在condition上等待"); condition.await(); } catch (Exception e) { e.printStackTrace(); } } finally { lock.unlock(); } System.out.println("线程t1执行完毕"); }); t1.start(); System.out.println("主线程执行中"); try { lock.lock(); System.out.println("主线程准备唤醒t1线程"); condition.signal(); } finally { lock.unlock(); } } }
使用lockSupport
package study; import java.util.concurrent.locks.LockSupport; public class Test2 { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { System.out.println("线程t1开始执行"); System.out.println("准备使用lockSupport让t1线程等待"); LockSupport.park(); System.out.println("线程t1结束等待,执行完毕"); }); t1.start(); System.out.println("主线程准备睡眠2秒"); Thread.sleep(2000); System.out.println("主线程睡眠完毕,准备唤醒t1线程"); LockSupport.unpark(t1); } }
3种方式的区别
-
Java 线程状态和等待唤醒机制和线程池的实现
2020-08-19 09:54:06主要介绍了Java 线程状态和等待唤醒机制和线程池的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 -
线程的等待和唤醒机制
2022-03-15 14:31:53三种让线程等待和唤醒的方法: LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程: 第一种方式:synchronized + wait + notify: 即使用Object中的wait方法让线程等待,使用Object中的notify方法唤醒线程: ...目录
三种让线程等待和唤醒的方法:
LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程:第一种方式:synchronized + wait + notify:
使用Object中的wait方法让线程等待,使用Object中的notify方法唤醒线程:
代码演示:
package com.fan.waitnotify; public class SyncDemo { //定义锁 static Object obj = new Object(); public static void main(String[] args) { new Thread(()->{ synchronized (obj){//加锁 System.out.println(Thread.currentThread().getName()+ "\t ----come in---"); try { obj.wait();//同一个锁去等待 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ "被唤醒--"); } },"A线程").start(); // new Thread(()->{ synchronized (obj){ obj.notify();//同一个锁去唤醒 System.out.println(Thread.currentThread().getName()+ "\t ---通知其他线程---"); } },"B线程").start(); } }
存在的弊端:
问题一:wait和notify 不能脱离synchronized代码块或者synchronized方法独自运行
报异常,证明 wait + notify不能脱离synchronized 代码块或者方法。问题二:wait + notify顺序不能颠倒,只能先等待后唤醒。
打印结果:发现处于阻塞状态:
被阻塞的结果,证明wait + notify顺序不能颠倒,只能先等待后唤醒。等待中的线程才能被唤醒,否则无法被唤醒。第二种方式:Lock + await + signal :
使用JUC包中的Condition的await方法让线程等待,使用signal方法唤醒线程:
代码演示:
package com.fan.waitnotify; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockDemo { //创建可重入的非公平锁 static Lock lock = new ReentrantLock(); static Condition condition = lock.newCondition(); public static void main(String[] args) { //如果这个方法我们只想运行一次,则直接写到线程内 new Thread(()->{ lock.lock();//加锁 try { System.out.println(Thread.currentThread().getName()+ "\t -----进来了----"); try { condition.await();//等待 } catch (InterruptedException e) { e.printStackTrace(); } // System.out.println(Thread.currentThread().getName()+ "\t -----被唤醒----"); } finally { lock.unlock();//解锁 } },"A").start(); new Thread(()->{ lock.lock(); try { condition.signal();//唤醒 System.out.println(Thread.currentThread().getName()+ "\t -----通知其他线程----"); } finally { lock.unlock(); } },"B").start(); } }
存在的问题:
问题一:lock和await和signal必须一起使用才行,await和signal不能脱离lock单独使用;
出现异常:证明lock和await和signal必须一起使用才行;
问题二:必须要先等待,后唤醒;调换顺序不能正常运行;
同样存在问题:必须要先等待,后唤醒;
总结:传统的synchronized 和Lock实现等待唤醒通知的约束:
第三种方式:LockSupport + park +unpark :
即LockSupport类的park方法可以 阻塞当前线程,使用unpark 方法唤醒指定被阻塞的线程:
注意:
park相当于wait,unpark相当于notifyLockSupport是什么:
park方法:
unpark方法:
代码演示:
package com.fan.waitnotify; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; public class ParkDemo { public static void main(String[] args) { Thread A = new Thread(()->{ //测试 先通知后阻塞: /*try { TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}*/ System.out.println(Thread.currentThread(). currentThread().getName()+"\t ----进来了----"); LockSupport.park();//当前线程被阻塞 System.out.println(Thread.currentThread(). currentThread().getName()+"\t ----被唤醒----"); },"A"); A.start(); //让A线程先运行 try { TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();} Thread B = new Thread(() -> { LockSupport.unpark(A);//唤醒 被阻塞的 线程实例 System.out.println(Thread.currentThread(). currentThread().getName()+"\t ----通知了----"); }, "B"); B.start(); } }
测试 先通知后阻塞:发现可以正常运行;
重点:
LockSupport面试题:
-
线程等待和唤醒的三种方式(Object、Condition、LockSupport)
2020-10-23 03:29:02Object中的wait()、notify()让线程等待和唤醒 Object.wait()、Object.notify()方法必须再synchronized修饰的代码块中才能正常使用,否则会报异常(语法不会显示有错误) 如下如果注释synchronized (obj)会报java.lang....Object中的
wait()
、notify()
让线程等待和唤醒Object.wait()
、Object.notify()
方法必须再synchronized
修饰的代码块中才能正常使用,否则会报异常(语法不会显示有错误
)如下如果注释
synchronized (obj)
会报java.lang.IllegalMonitorStateException: current thread is not owner
正常使用必须在synchronized中使用!
public static void main(String[] args) { Object obj = new Object(); new Thread(() -> { // synchronized (obj) { System.out.println(Thread.currentThread().getName() + "\t======== 进入"); try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "\t======== 被唤醒"); // } }, "A").start(); new Thread(() -> { //synchronized (obj) { obj.notify(); System.out.println(Thread.currentThread().getName()+"\t============ 通知"); //} }, "B").start(); }
Condition中的
await()
、signal()
让线程等待和唤醒Condition需要在ReentrantLock下使用,也就是需要上锁和释放锁,否则也会报
java.lang.IllegalMonitorStateException
public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); Condition condition=lock.newCondition(); new Thread(() -> { // lock.lock(); System.out.println(Thread.currentThread().getName() + "\t======== 进入"); try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); }finally { // lock.unlock(); } System.out.println(Thread.currentThread().getName() + "\t======== 被唤醒"); }, "A").start(); new Thread(() -> { // lock.lock(); try { condition.signal(); System.out.println(Thread.currentThread().getName()+"\t============ 通知"); } finally { // lock.unlock(); } }, "B").start(); }
LockSupport中的
park()
、unpark()
LockSupport调用unpark方法最多
只发放一个许可证
,调用park则需要消耗一个许可证。
换而言之如下的逻辑虽然调用了两次unpark,但LockSupport只发放一个许可证
LockSupport.unpark(t1)//需要传入参数线程t1 LockSupport.unpark(t1)//需要传入参数线程t1 LockSupport.park() LockSupport.park()// 线程会阻塞
另外LockSupport.park()和LockSupport.unpark()不影响正常使用阻塞
LockSupport.unpark(t1)//需要传入参数线程t1 LockSupport.park() // 上面的顺序和下面的调用顺序,两者的作用相同 LockSupport.park() LockSupport.unpark(t1)//需要传入参数线程t1
总而概之,LockSupport是一个线程阻塞的工具类,里面的所有方法都是静态的
相关文章:
-
java线程的等待和唤醒
2018-12-26 22:34:53notify() :唤醒在此对象监视器上等待的单个线程。 notifyAll() : 唤醒在此对象监视器上等待的所有线程。 wait():让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() ... -
Android消息机制(Handler机制) - 线程的等待和唤醒
2021-12-14 15:12:50我们都知道,Android的Handler机制,会在线程中开启消息循环,不断的从消息队列中取出消息,这个机制保证了主线程能够及时...这篇文章主要还是想聊聊,主线程等待和唤醒的时机的问题。 1.异步消息和同步消息 当Message -
线程等待与唤醒
2018-08-15 17:42:12wait(), notify(), notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口...而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()... -
java多线程通信之等待唤醒机制
2020-12-22 19:29:31典型实例有生产者和消费者,本文也通过实例来分析线程等待唤醒机制。 1、相关API介绍 public final void notify() 唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会任意选择唤醒... -
Java线程等待唤醒机制(加深理解)
2019-08-04 16:28:06这里就用到了线程等待唤醒机制,下面具体看一下。 等待唤醒机制示例 下面代码是一个简单的线程唤醒机制示例,主要就是在Activity启动的时候初始化并start线程,线程start后会进入等待状态,在onResume方法中执行... -
Java-线程状态和等待唤醒机制和线程池
2020-12-21 19:52:43等待唤醒案例(线程之间的通信) 实现: 等待唤醒案例:线程之间的通信 创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待) 创建一个老板线程(生产... -
linux对线程等待和唤醒操作(pthread_cond_timedwait 详解)
2019-08-18 18:16:44pthread_cond_timedwait()函数和pthread_cond_wait()函数,其实2个函数都差不多,我主要是要用pthread_cond_timedwait()函数。 pthread_cond_timedwait()函数有三个入口参数: (1)pthread_cond_t __cond:条件变量... -
代码分析Java中线程的等待与唤醒
2020-08-26 22:53:52本篇文章给大家分享了关于Java中线程的等待与唤醒的知识点内容,有需要的朋友们可以学习下。 -
线程的等待与唤醒机制
2017-05-09 11:03:26为了避免此类问题,我们会用到线程间的通信,而等待唤醒机制,就是线程间通信的一种形式。 等待唤醒机制用到的方法主要有: public final void wait() throws InterruptedException : 当前线程必 -
C++大量线程等待与唤醒
2020-06-20 18:01:36线程的等待和唤醒使用条件变量condition_variable和锁mutex结合实现,其中条件变量提供了wait(), notify(), notifyAll()等方法。 wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的... -
Java多线程5-线程等待与唤醒
2021-02-13 00:08:231、wait(),notify(),notifyAll()等方法介绍在object.java中,定义了wait(),notify(),notifyAll...而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒... -
Java中线程的等待与唤醒_动力节点Java学院整理
2020-08-30 10:26:38在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放...下面通过本文给大家介绍Java中线程的等待与唤醒知识,感兴趣的朋友一起看看吧 -
QT多线程线程等待与唤醒(QWaitCondition类的使用)
2020-04-22 17:40:23//唤醒消费者的线程 mutex.unlock(); } } class Consumer : public QThread//消费者 { public: Consumer(); void run(); }; Consumer::Consumer() { } void Consumer::run() { forever { mutex.lock(); if... -
Java 实现多线程切换等待唤醒交替打印奇偶数
2020-08-25 23:58:25主要介绍了Java 实现多线程切换等待唤醒交替打印奇偶数 ,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 -
Java多线程(五)——线程等待与唤醒
2021-02-26 10:07:36一、wait()、notify()、notifyAll()等方法介绍在Object.java中,定义了wait(), notify()和notifyAll()...而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤... -
Java消费者生产者|线程等待线程唤醒WaitNotifyDemo
2015-12-13 15:29:03Java写的消费者生产者模式,主要用到线程同步、线程等待和线程唤醒 -
java基本教程之java线程等待与java唤醒线程 java多线程教程
2020-09-04 17:45:06主要介绍了对线程等待/唤醒方法,文中使用了多个示例,大家参考使用吧 -
多线程:“等待唤醒”编程题
2021-01-20 03:01:24请用“等待唤醒”机制编写一个程序 要求: 第一个线程:遍历1–1000所有的数字,在遍历过程中,如果发现这个数字能同时被2,3,5,7整除,立即wait()等待,让第二个线程进入。 第二个线程:运行后,将一个计数器 + 1,... -
Java等待唤醒机制线程通信原理解析
2020-08-25 06:40:30主要介绍了Java等待唤醒机制线程通信原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 -
Java中wait(),notify()线程等待与唤醒- Java多线程系列教程四
2021-03-01 07:40:40Java中wait(),notify()线程等待与唤醒- Java多线程系列教程四在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。... -
Java线程阻塞和唤醒的几种方式
2020-12-17 10:04:09使用wait()方法来阻塞线程,使用notify()和notifyAll()方法来唤醒线程。 调用wait()方法后,线程将被阻塞,wait()方法将会释放当前持有的监视器锁(monitor),直到有线程调用notify/notifyAll()方法后方能继续执行。 ...