线程间通信

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

场景---两个线程,一个线程对当前数值加 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(); 
    } 
} 
相关推荐
重生之小比特24 分钟前
【Java SE】字符串 - String类
java·开发语言·intellij-idea
mldong6 小时前
给若依加审批流,不用 Flowable
java·spring boot·架构
Wang's Blog8 小时前
Java框架快速入门: Spring Security+OAuth2之数据库和实体类的RBAC改造
java·数据库·spring
讳疾忌医丶8 小时前
深度拆解 RocksDB 内核:基于 C++17 的 FIFO 调度状态机与温度阶梯自愈设计
java·c++·算法·架构
lsswear8 小时前
Python 并发 线程
开发语言·python
郑州光合科技余经理8 小时前
国际版外卖系统:税率字段怎么和订单主流程解耦
android·java·开发语言·前端·后端·php·ai编程
毅炼8 小时前
Rover-Suite 开源发布:轻量服务注册中心与网关一体化方案
java·后端·系统架构·gateway
软件课代表CiCi9 小时前
运行库是什么?电脑缺运行库怎么办?c++运行库缺失修复全攻略
开发语言·c++·windows·电脑·dll修复·dll丢失·运行库
梦想平凡9 小时前
百游棋牌源代码开发搭建教程(十):隔离部署、备份恢复与双端验收
java·前端·javascript·数据库·源代码管理
Ivanqhz9 小时前
MLIR OpBuilder
开发语言·python·mlir