JUC_01 线程阻塞、唤醒三种方式
三种方式总结: 一、synchronized: wait、notify、notifyAll 1、需要结合synchronized使用,否作会出现异常 2、必须先执行wait, 后执行notify或者notifyAll,否作会一直处于阻塞状态 二、Lock.condition: await、signal、signalAll 1、需要结合lock使用,否作会出现异常 2、必须先执行await, 后执行signal或者signalAll, 否作会一直处于阻塞状态 三、LockSupport: park、unpark 1、不依赖其它外部代码 2、park、unpark执行没有先后顺序 3、unpark方法同一时间最多只能获取一个许可证,只能通知一个park方法
package com.scwyfy.knowledge.juc; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; /** * LockSupport:park()与unpark() 用来阻塞和唤醒线程,不需要手动加锁即可实现,且对阻塞、唤醒顺序无要求 * 注意: 执行多次unpark(),最多也只能获取一个许可证(不会进行累加操作),只能唤醒一个park() * 例如:先执行两次unpark(),再执行两次park(), 第二个park()将会处于阻塞状态 * Synchronized: wait()与notify()或者notifyAll 用于阻塞和唤醒线程,需要结合Synchronized一起使用,否则将会产生异常 IllegalMonitorStateException * 且必须先wait(),再notify()。不然将会一直处于阻塞状态 * Lock * Condition: await()与signal()或者signalAll 用于阻塞和唤醒线程,需要结合Lock一起使用,否则将会产生异常 IllegalMonitorStateException * 且必须先await(),再signal()。不然将会一直处于阻塞状态 */ public class LockSupportDemo { public static void main(String[] args) { // synchronizedSolution(); // lockSolution(); // lockSupportSolution(); parkAndUnparkDemo(); } /** * unpark方法:许可证最多只能有一个 */ private static void parkAndUnparkDemo() { Thread thread = new Thread(() -> { try { TimeUnit.SECONDS.sleep(3L);// 目的先让执行unpark方法 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("准备执行两次park方法"); LockSupport.park(); System.out.println("已执行一次park方法"); LockSupport.park(); System.out.println("park方法执行完成"); }); thread.start(); new Thread(() -> { System.out.println("准备执行两次unpark方法"); LockSupport.unpark(thread); LockSupport.unpark(thread); System.out.println("unpark方法执行完成"); }).start(); } /** * LockSupport方式实现 阻塞、唤醒 */ private static void lockSupportSolution() { Thread a = new Thread(() -> { try { TimeUnit.SECONDS.sleep(3L); System.out.println(Thread.currentThread().getName() + " --- 进入"); } catch (InterruptedException e) { e.printStackTrace(); } LockSupport.park(); // 不需要依赖外部代码,park与unpark方法不用区分先后执行顺序 System.out.println(Thread.currentThread().getName() + " --- 出来"); }, "a"); a.start(); Thread b = new Thread(() -> { LockSupport.unpark(a); // 不需要依赖外部代码,park与unpark方法不用区分先后执行顺序 System.out.println(Thread.currentThread().getName() + " --- 通知"); }, "b"); b.start(); } /** * Lock.Condition方式实现阻塞、唤醒 */ private static void lockSolution() { Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); new Thread(() -> { try { // TimeUnit.SECONDS.sleep(3L);// 先signal,再await,会一直处于阻塞状态 lock.lock(); System.out.println(Thread.currentThread().getName() + " --- 进入"); condition.await(); // 不结合lock,await、signal方法会有异常IllegalMonitorStateException System.out.println(Thread.currentThread().getName() + " --- 出来"); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }, "A").start(); new Thread(() -> { try { lock.lock(); System.out.println(Thread.currentThread().getName() + " --- 通知"); condition.signal(); } finally { lock.unlock(); } }, "B").start(); } /** * synchronized方式实现阻塞、唤醒 */ private static void synchronizedSolution() { Object synchronizedLock = new Object(); new Thread(() -> { try { // TimeUnit.SECONDS.sleep(3L); // 先notify,再wait。会一直阻塞状态 synchronized (synchronizedLock) {// 不结合synchronized, wait、notify方法会有异常IllegalMonitorStateException System.out.println(Thread.currentThread().getName() + " --- 进入"); synchronizedLock.wait(); System.out.println(Thread.currentThread().getName() + " --- 出来"); } } catch (InterruptedException e) { e.printStackTrace(); } }, "A").start(); new Thread(() -> { synchronized(synchronizedLock) { synchronizedLock.notify(); System.out.println(Thread.currentThread().getName() + " --- 通知"); } }, "B").start(); } }