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();
    }
}
相关推荐
IceBing20 小时前
还在一个个连接 Arthas?这个开源平台支持批量诊断 JVM
java
SL_staff20 小时前
《如何用规则引擎替代if-else?JVS-Rules可视化编排比硬编码强在哪里?》
java·低代码·架构
绵绵细雨中的乡音20 小时前
监控显示一切正常,可用户根本打不开网站——Blackbox Exporter帮我找到了真相(1)
开发语言·php
c++之路20 小时前
CMake 系列教程(五):进阶技巧
c语言·开发语言·c++
踏着七彩祥云的小丑20 小时前
Go学习第5天:变量作用域 + 数组 + 指针
开发语言·学习·golang·go
Sam_Deep_Thinking21 小时前
java中的class到底是个什么东西?
java·开发语言·面试
swordbob21 小时前
Spring 3 级缓存解决循环依赖
java·spring
摇滚侠21 小时前
SpringMVC 入门到实战 获取请求参数 25-32
java·spring·intellij-idea
咖啡八杯21 小时前
【无标题】
java·后端·设计模式
mqiqe21 小时前
面试题-MyBatis 面试篇
java·面试·mybatis