背景:.start()之后,线程并不是立即创建,线程也并非按顺序创建。若想让线程顺序创建,则需要了解线程间的通信,以及下一节线程间的定制化通信
线程间通信
线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模 型来实现的。我们来基本一道面试常见的题目来分析
对于之前的操作方法的编写可以进行细化,分为三步:判断、执行、通知
题目: 场景—-两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1,要求 用线程间通信 。让两个线程对同一变量进行操作,让其完成交替操作的效果
synchronized方案
package com.atguigu.test;/*** volatile 关键字实现线程交替加减*/public class TestVolatile {/*** 交替加减* @param args*/public static void main( String[] args ){DemoClass demoClass = new DemoClass();new Thread( () - > {for ( int i = 0; i < 5; i++ ){demoClass.increment();}}, "线程 A" ).start();new Thread( () - > {for ( int i = 0; i < 5; i++ ){demoClass.decrement();}}, "线程 B" ).start();}}package com.atguigu.test;class DemoClass {/* 加减对象 */private int number = 0;/*** 加 1*/public synchronized void increment(){try {while ( number != 0 ) //判断{this.wait();}number++; //工作System.out.println( "--------" + Thread.currentThread().getName() + "加一成功----------,值为:" + number );notifyAll(); //通知}catch ( Exception e ) {e.printStackTrace();}}/*** 减一*/public synchronized void decrement(){try {while ( number == 0 ) //判断{this.wait();}number--; //工作System.out.println( "--------" + Thread.currentThread().getName() + "减一成功----------,值为:" + number );notifyAll(); //通知}catch ( Exception e ) {e.printStackTrace();}}}
Lock方案
package com.atguigu.test;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;class DemoClass {/* 加减对象 */private int number = 0;/* 声明锁 */private Lock lock = new ReentrantLock();/* 声明钥匙 */private Condition condition = lock.newCondition();/*** 加 1*/public void increment(){try {lock.lock();while ( number != 0 ) //判断{condition.await();}number++; /工作System.out.println( "--------" + Thread.currentThread().getName() + "加一成功----------,值为:" + number );condition.signalAll(); //通知}catch ( Exception e ) {e.printStackTrace();} finally {lock.unlock();}}/*** 减一*/public void decrement(){try {lock.lock();while ( number == 0 ){condition.await();}number--;System.out.println( "--------" + Thread.currentThread().getName() + "减一成功----------,值为:" + number );condition.signalAll();}catch ( Exception e ) {e.printStackTrace();} finally {lock.unlock()}}}
wait()虚假判断
问题来源于wait()在哪里睡就会在哪里醒。当在判断和工作之间睡就会在此醒,这样就会让之前的判断失效,造成虚假判断。
所以把判断从if改为while,这样即使睡醒也要再参与判断,不会继续执行
