Java高性能编程-java基础-1.1.5线程通信

线程通信

       JDK 对于需要多线程写作完成的场景,提供对应API 支持

      多线程协作场景:生产者 - 消费者模型。 (线程阻塞、线程唤醒)

      使用方式: wait / notify 和 park / unpark

 wait / notify

      只能由同一对象锁的持有者线程调用,也就是写在同步块里面,否则会抛出IllegalMointorStateException 异常;

      wait 方法导致当前线程等待,加入该对象的等待集合中,并放弃当前持有的对象锁;

      notify / notifyAll 方法唤醒一个或所有正等待该对象锁的线程

      注: 虽然wait自动解锁,但对顺序由要求,如果notify 被调用后才开始wait 方法线程会永远处于waiting 状态

public class WaitDemo{

	public static Object target = null;

	@Test
	public void waitNotifyTest() throws Exception {

		new Thread(() -> {
			if (target == null) {
				synchronized (this) {
					try {
						System.out.println("1、进入等待。");
						this.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}

			System.out.print("2、获取目标,完成。");
			
		}).start();

		Thread.sleep(3000L);
		target = new Object();
		synchronized (this) {
			this.notifyAll();
			System.out.println("3、通知消费者。");
		}

	}
}

   运行结果

1、进入等待。
3、通知消费者。
2、获取到目标,完成,

    执行顺序

                       

Park / Unpark 

       线程调用park,则等待“许可”,unpark 为指定线程提供“许可”

       不要求 park 和 unpark 调用顺序

     

demo

	@Test
	public void parkUnparkTest() throws Exception {
		Thread consumerTread = new Thread(() -> {
			if (target == null) {
				System.out.println("1、进入等待");
				LockSupport.park();
			}
			System.out.println("2、获取到目标,完成");
		});
		consumerTread.start();

		Thread.sleep(3000L);
		target = new Object();
		LockSupport.unpark(consumerTread);
		System.out.println("3.通知消费者。");
	}

 运行结果

1、进入等待
3.通知消费者。
2、获取到目标,完成

  

伪唤醒问题

     之前代码用if 语句判断时候进入等待状态,是错误的

     官方建议在循环中检查等待条件,原因是处于等待状态的线程可能会受到错误唤醒,如果不在循环中检查等待条件,程序会在没有满足的结束条件情况下退出;

     伪唤醒是指并非因为notify, notifyall,unpark等api调用唤醒,而是底层原因

  

导致死锁

	public void parkUnparkDeadLockTest() throws Exception {
		Thread consumerThread = new Thread(() -> {
			System.out.println("1.1、进入等待。");
			if (target == null) {
				System.out.println("1.2、进入等待。");
				synchronized (this) {
					LockSupport.park();
				}
			}
			System.out.println("2.买到包子,回家。");

		});
		consumerThread.start();
		target = new Object();

		synchronized (this) {
			LockSupport.unpark(consumerThread);
		}
		System.out.println("3.通知消费者。");
	}

  

 

    

      

原文地址:https://www.cnblogs.com/Jomini/p/13069235.html