线程间通信

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

场景---两个线程,一个线程对当前数值加 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(); 
    } 
} 
相关推荐
WL学习笔记27 分钟前
日期类(C++)
开发语言·c++·日期类实现
【JAVA】玩家34 分钟前
Spring核心原理全解析:从零到生产实战
java·后端·spring
Wang's Blog1 小时前
Java框架 SpringCloud 快速入门: 实现 Feign 最佳实践(抽取方式)
java·spring cloud
谢亮_vipxieliang1 小时前
Go map与结构体的正确使用
开发语言·golang·哈希算法
H.莓飛1 小时前
【C++】命名空间、缺省参数、函数重载与引用
linux·开发语言·c++·visual studio
xxwl5851 小时前
数据结构知识点和代码实现总结(C语言实现)
c语言·开发语言·数据结构
MandalaO_O2 小时前
IDEA 开发(快捷键 + 调试 + 序列化)
java·ide·intellij-idea
xiaoqiMikko3 小时前
JVM 线上排查实战(七):jps 看不见它、jstack 连不上它,可它明明活得好好的
java·jvm
狼爷3 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言
念何架构之路3 小时前
zap扩展生态与总结
java·前端·数据库