java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)
java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)
示例回顾
package test1; import java.util.LinkedList; /** * 消息队列MessageQueue 测试 */ public class T14 { public static void main(String[] args) { final RefactorMessageQueue mq = new RefactorMessageQueue(5); System.out.println("***************task begin***************"); //创建生产者线程并启动 for (int i = 0; i < 20; i++) { new Thread(() -> { while (true) { mq.set(new Message()); } }, "producer"+i).start(); } //创建消费者线程并启动 new Thread(() -> { while (true) { mq.get(); } }, "consumer").start(); } } /** * 消息队列 */ class RefactorMessageQueue { /** * 队列最大值 */ private final int max; /* * 锁 * */ private final byte[] lock = new byte[1]; /** * final确保发布安全 */ final LinkedList<Message> messageQueue = new LinkedList<>(); /** * 构造函数默认队列大小为10 */ public RefactorMessageQueue() { max = 10; } /** * 构造函数设置队列大小 */ public RefactorMessageQueue(int x) { max = x; } public void set(Message message) { synchronized (lock) { //如果已经大于队列个数,队列满,进入等待 while (messageQueue.size() > max) { try { System.out.println(Thread.currentThread().getName() + " : queue is full ,waiting..."); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果队列未满,生产消息,随后通知lock上的等待线程 //每一次的消息生产,都会通知消费者 System.out.println(Thread.currentThread().getName() + " : add a message"); messageQueue.addLast(message); lock.notifyAll(); } } public void get() { synchronized (lock) { //如果队列为空,进入等待,无法获取消息 while (messageQueue.isEmpty()) { try { System.out.println(Thread.currentThread().getName() + " : queue is empty ,waiting..."); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //队列非空时,读取消息,随后通知lock上的等待线程 //每一次的消息读取,都会通知生产者 System.out.println(Thread.currentThread().getName() + " : get a message"); messageQueue.removeFirst(); lock.notifyAll(); } } }
- synchronized关键字
- 监视器方法
显式锁逻辑
Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); }
package test2; import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class T26 { public static void main(String[] args) { final RefactorMessageQueue mq = new RefactorMessageQueue(5); System.out.println("***************task begin***************"); //创建生产者线程并启动 for (int i = 0; i < 20; i++) { new Thread(() -> { while (true) { mq.set(new Message()); } }, "producer" + i).start(); } //创建消费者线程并启动 new Thread(() -> { while (true) { mq.get(); } }, "consumer").start(); } /** * 消息队列中存储的消息 */ static class Message { } /** * 消息队列 */ static class RefactorMessageQueue { /** * 队列最大值 */ private final int max; /* * 锁 * */ private final Lock lock = new ReentrantLock(); /** * 条件变量 */ private final Condition condition = lock.newCondition(); /** * final确保发布安全 */ final LinkedList<Message> messageQueue = new LinkedList<>(); /** * 构造函数默认队列大小为10 */ public RefactorMessageQueue() { max = 10; } /** * 构造函数设置队列大小 */ public RefactorMessageQueue(int x) { max = x; } public void set(Message message) { lock.lock(); try { //如果已经大于队列个数,队列满,进入等待 while (messageQueue.size() > max) { try { System.out.println(Thread.currentThread().getName() + " : queue is full ,waiting..."); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果队列未满,生产消息,随后通知lock上的等待线程 //每一次的消息生产,都会通知消费者 System.out.println(Thread.currentThread().getName() + " : add a message"); messageQueue.addLast(message); condition.signalAll(); } finally { } lock.unlock(); } public void get() { lock.lock(); try { //如果队列为空,进入等待,无法获取消息 while (messageQueue.isEmpty()) { try { System.out.println(Thread.currentThread().getName() + " : queue is empty ,waiting..."); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } //队列非空时,读取消息,随后通知lock上的等待线程 //每一次的消息读取,都会通知生产者 System.out.println(Thread.currentThread().getName() + " : get a message"); messageQueue.removeFirst(); condition.signalAll(); } finally { lock.unlock(); } } } }
/* * 锁 * */ private final Lock lock = new ReentrantLock(); /** * 条件变量 */ private final Condition condition = lock.newCondition();
- 使用lock.lock();以及lock.unlock(); 替代了synchronized(lock)
- 使用condition的await和signalAll方法替代了lock.wait()和 lock.notifyAll
package test2; import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class T27 { public static void main(String[] args) { final RefactorMessageQueue mq = new RefactorMessageQueue(5); System.out.println("***************task begin***************"); //创建生产者线程并启动 for (int i = 0; i < 20; i++) { new Thread(() -> { while (true) { mq.set(new Message()); } }, "producer" + i).start(); } //创建消费者线程并启动 new Thread(() -> { while (true) { mq.get(); } }, "consumer").start(); } /** * 消息队列中存储的消息 */ static class Message { } /** * 消息队列 */ static class RefactorMessageQueue { /** * 队列最大值 */ private final int max; /* * 锁 * */ private final Lock lock = new ReentrantLock(); /** * 条件变量,用于消费者,非空即可消费 */ private final Condition notEmptyCondition = lock.newCondition(); /** * 条件变量,用于生产者,非满即可生产 */ private final Condition notFullCondition = lock.newCondition(); /** * final确保发布安全 */ final LinkedList<Message> messageQueue = new LinkedList<>(); /** * 构造函数默认队列大小为10 */ public RefactorMessageQueue() { max = 10; } /** * 构造函数设置队列大小 */ public RefactorMessageQueue(int x) { max = x; } public void set(Message message) { lock.lock(); try { //如果已经大于队列个数,队列满,进入等待 while (messageQueue.size() > max) { try { System.out.println(Thread.currentThread().getName() + " : queue is full ,waiting..."); //如果满了,生产者在“非满”这个条件上等待 notFullCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果队列未满,生产消息,随后通知lock上的等待线程 //每一次的消息生产,都会通知消费者 System.out.println(Thread.currentThread().getName() + " : add a message"); messageQueue.addLast(message); //生产后,增加了消息,非空条件满足,需要唤醒消费者 notEmptyCondition.signalAll(); } finally { } lock.unlock(); } public void get() { lock.lock(); try { //如果队列为空,进入等待,无法获取消息 while (messageQueue.isEmpty()) { try { System.out.println(Thread.currentThread().getName() + " : queue is empty ,waiting..."); //如果空了,消费者需要在“非空”条件上等待 notEmptyCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } //队列非空时,读取消息,随后通知lock上的等待线程 //每一次的消息读取,都会通知生产者 System.out.println(Thread.currentThread().getName() + " : get a message"); messageQueue.removeFirst(); //消费后,减少了消息,所以非满条件满足,需要唤醒生产者 notFullCondition.signalAll(); } finally { lock.unlock(); } } } }
总结
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
java代理模式
前言: 看有关于技术的文章需要带着问题去看,我上周在公司做了一场设计模式的技术分享,在会上又不同的小伙伴提出了很多疑问,那么今天我就来解决一下这一些疑问,非常感谢参与会议的小伙伴。 问题: 一、什么是设计模式? 二、为什么JDK动态代理与CGLIB动态代理生成的源代码是差不多的? 三、代理模式相比直接使用接口有什么好处吗? 四、如果接口被多个类实现会怎样? 问题1:什么是设计模式 设计模式是一种经验能够使新手更加简单的使用前人的经验和方案。 可以避免重复劳动,就像一句在这个行业流行的话不要重复造轮子。 设计模式是针对特定上下文的特定问题的解决方案,解决方案被抽象化、模版化、就是设计模式,学习设计模式的关键是理解,理解方法理解思想理解观念。 不是为了使用设计模式而,设计的根本是为了可复用、可拓展、高性能,不要为了使用设计模式而使用,一定要结合实际环境的去考虑整个问题。 每一种模式有四个基本元素:模式名称、问题描述、应用场景、应用后效果。 设计模式在应用中遵循六大原则: 开闭原则:对扩展开放,对修改关闭。 里氏代换原则:任何基类可以出现的地方,子类一定可以出现。 依赖倒转原则:针对接口编程...
- 下一篇
关于如何通过Maven仓库安装Spire.PDF for Java的示范教程
关于如何通过Maven仓库安装Spire.PDF for Java的示范教程 Spire系列库中已发布的Java产品目前有三个,即Spire.PDF for Java、Spire.Presentation for Java、Spire.Barcode for Java。使用该Java产品,除了可以从官网:https://www.e-iceblue.cn/Downloads.html下载,也可以通过Maven来安装使用。本教程中,以通过Maven安装Spire.PDF for Java为例介绍具体安装方法和步骤。 首先,在pom.xml文件中配置Maven仓库路径。 <repositories> <repository> <id>com.e-iceblue</id> <name>e-iceblue</name> <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url> </repository> </r...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装