Java实现线程间的通讯--使用synchronized关键字和JUC方式实现

Java实现线程间的通讯--使用synchronized关键字和JUC方式实现

即比较经典的生产者和消费者问题,生产者在资源为0时进行生产;在资源不为0时,消费者进行消费,生产者和消费者交替执行。多线程的运行由CPU分配执行的,要交替执行,也就是实现

--

当资源为0时,如果消费者获取执行权,则等待并唤醒生产者生产;如果资源不为0,则消费者消费后,再释放锁唤醒生产者生产。

同样的

当资源不为0时,如果生产者获取执行权,则等待并唤醒消费者进行消费;如果资源为0,则生产者生产后,再释放锁唤醒消费者消费。

使用synchronized关键字实现

技术栈:synchronized + wait() + notifyAll()

实现类

java 复制代码
//生产者和消费者各实现为一个方法
public class SynchronizedCommunication {

	//初始化一个变量,作为操作的同步资源数
    private int count;

    //生产者操作
    public synchronized void add(){
        try{
            //对共同资源判断,当存在资源
            while(count != 0) {
                //则生产线程进入等待状态
                this.wait();
            }
                //生产者生产
                count++;
                //打印一下当前线程及操作的共同资源的值,便于理解
                System.out.println(Thread.currentThread().getName()+"::"+count);
        }catch (InterruptedException e){
            throw new RuntimeException(e);
        }finally {
            //唤醒消费者消费
            this.notifyAll();
        }
    }

    //消费者操作
    public synchronized void subtract(){
        try{
            //对共同资源判断
            while (count == 0){
                //则消费线程进入等待状态
                this.wait();
            }
                //消费者消费
                count--;
                System.out.println(Thread.currentThread().getName()+"::"+count);
        }catch (InterruptedException e){
            throw new RuntimeException(e);
        }finally {
            //唤醒生产者生产
            this.notifyAll();
        }
    }
}

注意:上述代码中判断使用的时while循环,因为如果实例化的线程不止一个生产者和消费者时,判断不止一次,if()语句来进行判断会出现假醒问题,可能操作的共同资源有负数的情况。所以不管线程是在什么情况下被唤醒,都要进行判断,符合要求再进行生产或是消费的动作。

测试类

java 复制代码
//这里创建了四个线程,分别两个生产者,两个消费者;可以看一下,如果在这种情况下,使用if语句来进行判断,可能出现假醒问题
public class SynchronizedCommunicationTest {

    public static void main(String[] args) {
        //实例化共同资源类对象
        SynchronizedCommunication sc = new SynchronizedCommunication();

        //创建生产者线程,匿名内部类实现操作
        Thread t0 = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    sc.add();
                }
            }
        },"生产者A");

        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    sc.subtract();
                }
            }
        },"消费者B");

        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    sc.add();
                }
            }
        },"生产者C");

        Thread t3 = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    sc.subtract();
                }
            }
        },"消费者D");
        t0.start();
        t1.start();
        t2.start();
        t3.start();
    }
}

JUC方式实现

技术栈:Lock锁接口 + Condition接口

实现类

java 复制代码
            lock.unlock();
        }
    }

    public void subtract(){
        lock.lock();
        try {
            while (count == 0) {
                condition.await();
            }
            System.out.println(Thread.currentThread().getName()+"---"+(--count));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }finally {
            condition.signalAll();
            lock.unlock();
        }
    }
}

测试类

java 复制代码
public class LockCommunicationTest {
    public static void main(String[] args) {
        LockCommunication lc = new LockCommunication();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    lc.add();
                }
            }
        },"生产者1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    lc.add();
                }
            }
        },"生产者2");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    lc.subtract();
                }
            }
        },"消费者1");
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    lc.subtract();
                }
            }
        },"消费者2");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
相关推荐
杨杨杨大侠7 小时前
都能接模型、RAG 和 MCP,Java Agent 框架到底差在哪?
java
破茧蝴蝶8 小时前
Python分布式爬虫完整教程
开发语言·python
狗凯之家源码网8 小时前
全新 PHP 轻量客服聊天室源码深度评测
开发语言·php·聊天室系统
远离UE48 小时前
UE5 Substrate Thin Film 源码拆析
开发语言·javascript·ue5
keyipatience8 小时前
JavaScript学习(1)书写位置,变量、数据类型、运算符
开发语言·前端·javascript·css·学习
Thinker QAQ8 小时前
并发编程(九):BlockingQueue 与 Channel——语言层的原子性、可见性与有序性
java·python·go·并发编程·channel·blockingqueue·message passing
栈帧之外9 小时前
【C++】STL之set
开发语言·c++
霸道流氓气质10 小时前
RAG 可观测性与生产监控实战:四层遥测模型、五大仪表盘与 OpenTelemetry 全链路追踪的 Java 生产级实现
java·人工智能·python
AOI小白新手上路10 小时前
autodl常用的tar 打包下载(数据集)命令手册:逐段拆解与套用模板
java·大数据·数据库
catchadmin10 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.4.1 发布,新增 MCP 支持
开发语言·php