线程间通信

线程间通信的模型有两种:共享内存 和 消息传递,以下方式都是基本这两种模型来实现的。

场景---两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1。要求用线程间通信

3.1 synchronized方案

使用 wait(); notify();

java 复制代码
public class TestMain { 
   /** 
    ● 交替加减
    */ 
    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(); 
    } 
} 
java 复制代码
class DemoClass{     
    
    //加减对象 
    private int number = 0; 
 
    /** 
     * 加 1 
     */ 
    public synchronized void increment() { 
        try { 
            while (number != 0){ 
                this.wait(); 
            } 
            number++; 
            System.out.println(currentThread().getName() + "加一成功,值为:" + number); 
            //唤醒其他的线程
            notifyAll(); 
        }catch (Exception e){ 
            e.printStackTrace(); 
        } 
    } 
 
    /** 
     * 减一 
     */ 
    public synchronized void decrement(){ 
        try { 
            while (number != 1){ 
                this.wait(); 
            } 
            number--; 
            System.out.println(currentThread().getName() + "减一成功,值为:" + number); 
            notifyAll(); 
        }catch (Exception e){ 
            e.printStackTrace(); 
        } 
    } 
} 

3.2 Lock 方案

使用 Condition condition.await(); condition.signal();

java 复制代码
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(currentThread().getName() + "加一成功,值为:" + number);
            //	通知其他等待的线程
            condition.signalAll(); 
        }catch (Exception e){ 
            e.printStackTrace();         
        }finally {             
            lock.unlock(); //释放锁
        } 
    } 
 
    /** 
     * 减一 
     */ 
    public void decrement(){ 
        try {             
            lock.lock();             
            while (number != 1){                 
                condition.await(); 
            } 
            number--; 
            System.out.println(currentThread().getName() + "减一成功,值为:" + number); 
            condition.signalAll(); 
        }catch (Exception e){ 
            e.printStackTrace();         
        }finally {             
            lock.unlock();                                                   
        } 
    } 
} 
java 复制代码
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 
 
class DemoClass{ 
    //通信对象:0--打印 A  1---打印 B  2----打印 C 
    private int number = 0; 
    //声明锁     
    private Lock lock = new ReentrantLock(); 
    //声明钥匙 A 
    private Condition conditionA = lock.newCondition(); 
    //声明钥匙 B 
    private Condition conditionB = lock.newCondition(); 
    //声明钥匙 C 
    private Condition conditionC = lock.newCondition(); 
}

3.4 线程间定制化通信

3.4.1 案例介绍

问题: A 线程打印 5 次 A,B 线程打印 10 次 B,C 线程打印 15 次 C 。

按照此顺序循环 10 轮

3.4.2 实现流程

代码如下:

java 复制代码
//	标志位 AA 1   BB 2  CC 3
private int number = 1; 

Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition(); 
private Condition conditionB = lock.newCondition(); 
private Condition conditionC = lock.newCondition(); 

//	5 次
public void printA(int j){ 
    try {             
        lock.lock();             
        while (number != 1){
            conditionA.await(); 
        } 
        System.out.println(currentThread().getName() + "输出 A,第" + j + " 轮开始"); 
        // 输出 5 次 A 
        for (int i = 0; i < 5; i++) { 
            System.out.println("A"); 
        } 
        // 修改标志位           
        number = 2;             
        //唤醒 B
        conditionB.signal(); 
    } catch (Exception e){ 
        e.printStackTrace();         
    } finally {
        lock.unlock(); 
    } 
} 

//	10 次
public void printB(int j){ 
    try {             
        lock.lock();
        while (number != 2){
            conditionB.await(); 
        } 
        System.out.println(currentThread().getName() + "输出 B,第" + j + " 轮开始"); 
        //输出 10 次 B 
        for (int i = 0; i < 10; i++) { 
            System.out.println("B"); 
        } 
        // 修改标志位
        number = 3;
        //唤醒 C
        conditionC.signal(); 
    } catch (Exception e){ 
        e.printStackTrace();         
    }finally {
        lock.unlock(); 
    }
}

//	15 次
public void printC(int j){ 
    try {             
        lock.lock();
        while (number != 3){
            conditionC.await(); 
        } 
        System.out.println(currentThread().getName() + "输出 C,第" + j + " 轮开始"); 
        //输出 15 次 C 
        for (int i = 0; i < 15; i++) { 
        System.out.println("C"); 
        } 
        System.out.println("-----------------------------------------"); 
        //	修改标志位
        number = 1;
        //唤醒 A
        conditionA.signal(); 
    } catch (Exception e){ 
        e.printStackTrace(); 
    } finally {
        lock.unlock(); 
    } 
} 

测试类

java 复制代码
/** 
● 关键字实现线程交替加减 
*/ 
public class TestVolatile { 
    /** 
    ● 交替加减 
    ● @param args 
    */ 
    public static void main(String[] args){ 
        
        DemoClass demoClass = new DemoClass(); 
        
        new Thread(() ->{             
            for (int i = 1; i <= 10; i++) {                 
                demoClass.printA(i); 
            } 
        }, "A 线程").start(); 
        
        new Thread(() ->{
            for (int i = 1; i <= 10; i++) { 
                demoClass.printB(i); 
            } 
        }, "B 线程").start(); 
        
        new Thread(() ->{
            for (int i = 1; i <= 10; i++) {
                demoClass.printC(i); 
            } 
        }, "C 线程").start(); 
    } 
} 
相关推荐
月夕·花晨1 小时前
Gateway-过滤器
java·分布式·spring·spring cloud·微服务·gateway·sentinel
hssfscv2 小时前
JAVA学习笔记——9道综合练习习题+二维数组
java·笔记·学习
人工干智能3 小时前
科普:Python 中,字典的“动态创建键”特性
开发语言·python
初听于你4 小时前
缓存技术揭秘
java·运维·服务器·开发语言·spring·缓存
小蒜学长5 小时前
springboot多功能智能手机阅读APP设计与实现(代码+数据库+LW)
java·spring boot·后端·智能手机
长路归期无望6 小时前
C语言小白实现多功能计算器的艰难历程
c语言·开发语言·数据结构·笔记·学习·算法
是大强6 小时前
stm32摇杆adc数据分析
开发语言
蓝莓味的口香糖7 小时前
【JS】什么是单例模式
开发语言·javascript·单例模式
zizisuo7 小时前
解决在使用Lombok时maven install 找不到符号的问题
java·数据库·maven
linux kernel7 小时前
第二十三讲:特殊类和类型转换
开发语言·c++