zoukankan      html  css  js  c++  java
  • 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.通知消费者。");
    	}
    

      

     

        

          

  • 相关阅读:
    人工智能系统
    Maven tomcat插件配置和使用
    青春谁不糊涂3
    假设但是学习java入门,请离开SSH稍远
    Linux下top订购具体解释
    Unity3d + NGUI 多分辨率适应
    Delphi 注册文件类型 设置文件图标
    如何创建自定义的文件类型关联
    delphi 中字符串与16进制、10进制转换函数
    十六进制字符串转化成字符串输出HexToStr(Delphi版、C#版)
  • 原文地址:https://www.cnblogs.com/Jomini/p/13069235.html
Copyright © 2011-2022 走看看