线程间通信

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

场景---两个线程,一个线程对当前数值加 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(); 
    } 
} 
相关推荐
FQNmxDG4S2 小时前
Java多线程编程:Thread与Runnable的并发控制
java·开发语言
前端老石人2 小时前
HTML 字符引用完全指南
开发语言·前端·html
matlab_xiaowang2 小时前
Redux 入门:JavaScript 可预测状态管理库
开发语言·javascript·其他·ecmascript
虹科网络安全3 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
axng pmje3 小时前
Java语法进阶
java·开发语言·jvm
rKWP8gKv73 小时前
Java微服务性能监控:Prometheus与Grafana集成方案
java·微服务·prometheus
老前端的功夫3 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_435287923 小时前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
小江的记录本3 小时前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
止语Lab3 小时前
从手动到框架:Go DI 演进的三个拐点
开发语言·后端·golang