博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java基础学习——多线程(线程间通信-生产者消费者代码示例)
阅读量:6969 次
发布时间:2019-06-27

本文共 4157 字,大约阅读时间需要 13 分钟。

JDK 1.5提供了多线程升级方案

将同步synchronized替换成了显示的Lock操作。可以实现唤醒、冻结指定的线程。

Lock接口

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。
线程间通信Condition接口
Condition可以替代传统的线程间通信,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll()。该对象可以通过Lock锁进行获取。

传统线程的通信方式,Condition都可以实现。

注意,Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用newCondition()方法。

ReentrantLock类
Java.util.concurrent.lock 中的Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。

ReentrantLock 类实现了Lock ,它拥有与synchronized 相同的并发性和内存语义,但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。(换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。)

用法示例:

private Lock lock = new ReentrantLock();//定义多态ReentrantLock类对象private Condition cond_pro = lock.newCondition();//Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用Lock对象的newCondition()方法。private Condition cond_con = lock.newCondition();//一个lock可以有多个相关的condition

首先创建一个ReentrantLock类的多态对象,即建立一把锁。然后将这把锁与两个Condition对象关联。

实例:

import java.util.concurrent.locks.*;    class ProducerConsumerDemo     {        public static void main(String[] args)         {            Resource r = new Resource();            Producer pro = new Producer(r);//生产者对象            Consumer con = new Consumer(r);//消费者对象                Thread t1 = new Thread(pro);            Thread t2 = new Thread(pro);            Thread t3 = new Thread(con);            Thread t4 = new Thread(con);                t1.start();            t2.start();            t3.start();                t4.start();                }    }        class Resource    {        private String name;        private int count = 1;        private boolean flag = false;        private Lock lock = new ReentrantLock();//定义一个实现Lock接口的ReentrantLock类对象        private Condition cond_pro = lock.newCondition();//Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用Lock对象的newCondition()方法。           private Condition cond_con = lock.newCondition();//一个lock可以有多个相关的condition                public  void set(String name) throws InterruptedException//生产方法                                       //注意这里抛出await()方法异常声明,交给调用者处理        {            lock.lock();    //手动加同步锁            try            {                  while (flag)    //if→while 此时若生产完一个以后唤醒了另一个生产者,则再次判断,避免了两个生产者同时生产                    cond_pro.await();       //冻结生产方法                this.name = name+"____"+count++;                System.out.println(Thread.currentThread().getName()+"_______"+"生产者"+this.name);                flag = true;                cond_con.signal(); //唤醒消费方法,利用了condition的signal()指定唤醒对象                    }            finally    //            {                lock.unlock();            }        }            public  void out()throws InterruptedException        {            lock.lock();            try                {                    while (!flag)                        cond_con.await();                    System.out.println(Thread.currentThread().getName()+"______"+"消费者"+this.name);                    flag = false;                    cond_pro.signal();                }            finally    //释放锁必须得到执行            {                lock.unlock();            }        }    }        class Consumer implements Runnable    {        private Resource res;        public Consumer(Resource res)        {            this.res = res;        }        public void run()        {            while (true)            {                try    //由于out()方法抛出了异常声明,这里必须捕获。                {                    res.out();                    }                catch (InterruptedException e)                {                }            }                    }    }        class Producer implements Runnable    {        private Resource res;        public Producer(Resource res)        {                        this.res = res;                                    }        public void run()        {            while (true)            {                    try                {                    res.set("+商品+");                                }                catch (InterruptedException e)                {                }            }            }    }

执行上述代码,观察结果:

clipboard.png

可以看到,多个线程同时生产、消费,由于指定唤醒互异线程,因此并不会引起错误。

转载地址:http://xissl.baihongyu.com/

你可能感兴趣的文章
SSDB Windows安装包
查看>>
使用gulp-connect实现web服务器
查看>>
Android APP弱网测试问题和解决分析
查看>>
深入研究EF Core AddDbContext 引起的内存泄露的原因
查看>>
set集合
查看>>
今天不谈技术,说说一些常用的软件~By 逆天
查看>>
Python爬虫入门二之爬虫基础了解
查看>>
java入门概念个人理解之访问修饰符
查看>>
分布式 vs 集群 主从 vs 集群
查看>>
javascript数组操作汇总
查看>>
静态链表
查看>>
Ubuntu 12.04中文输入法的安装
查看>>
[转] 你真的了解回流和重绘吗
查看>>
[转] babel-present-env 与 babel-polyfill 学习总结
查看>>
openstack学习(一)kvm-libvirt
查看>>
使用pytesseract识别简单验证码
查看>>
1103 Integer Factorization
查看>>
Promise 简易实现 - 面试专用
查看>>
PHP —— 读取文件到二维数组
查看>>
Mysql中select的正确姿势
查看>>