线程间通信

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

场景---两个线程,一个线程对当前数值加 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(); 
    } 
} 
相关推荐
xqqxqxxq5 小时前
Java AI智能P图工具技术笔记
java·人工智能·笔记
谷雨不太卷6 小时前
进程的状态码
java·前端·算法
jieyucx6 小时前
Go语言深度解剖:Map扩容机制全解析(增量扩容+等量扩容+渐进式迁移)
开发语言·后端·golang·map·扩容策略
顾温6 小时前
default——C#/C++
java·c++·c#
空中海6 小时前
02 ArkTS 语言与工程规范
java·前端·spring
楚国的小隐士6 小时前
在AI时代,如何从0接手一个项目?
java·ai·大模型·编程·ai编程·自闭症·自闭症谱系障碍·神经多样性
脏脏a6 小时前
【C++模版】泛型编程:代码复用的终极利器
开发语言·c++·c++模版
island13146 小时前
【C++仿Muduo库#3】Server 服务器模块实现上
服务器·开发语言·c++
散峰而望6 小时前
【算法竞赛】C/C++ 的输入输出你真的玩会了吗?
c语言·开发语言·数据结构·c++·算法·github
小龙报6 小时前
【C语言】内存里的 “数字变形记”:整数三码、大小端与浮点数存储真相
c语言·开发语言·c++·创业创新·学习方法·visual studio