- 浏览: 5158958 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
silence19841230:
先拿走看看
SpringBoot2.0开发WebSocket应用完整示例 -
wallimn:
masuweng 写道发下源码下载地址吧!三个相关文件打了个包 ...
SpringBoot2.0开发WebSocket应用完整示例 -
masuweng:
发下源码下载地址吧!
SpringBoot2.0开发WebSocket应用完整示例 -
masuweng:
SpringBoot2.0开发WebSocket应用完整示例 -
wallimn:
水淼火 写道你好,我使用以后,图标不显示,应该怎么引用呢,谢谢 ...
前端框架iviewui使用示例之菜单+多Tab页布局
转自:http://josh-persistence.iteye.com/blog/1924725
在很多情况下,多线程间仅仅同步是不够的,还需要线程与线程协作(通信),生产者/消费者模式是一个经典的线程同步以及通信的模型。
假设有这样一种情况,有一个篮子,篮子里只能放一个鸡蛋,A线程专门往篮子里放鸡蛋,如果篮子里有鸡蛋,则一直等到篮子里没鸡蛋,B线程专门从篮子里取鸡蛋,如果篮子里没鸡蛋,则一直等到篮子里有鸡蛋。这里篮子是一个互斥区,每次放鸡蛋是互斥的,每次取鸡蛋也是互斥的,A线程放鸡蛋,如果这时B线程要取鸡蛋,由于A没有释放锁,B线程处于等待状态,进入阻塞队列,放鸡蛋之后,要通知B线程取鸡蛋,B线程进入就绪队列,反过来,B线程取鸡蛋,如果A线程要放 鸡蛋,由于B线程没有释放锁,A线程处于等待状态,进入阻塞队列,取鸡蛋之后,要通知A线程放鸡蛋,A线程进入就绪队列。我们希望当篮子里有鸡蛋时,A线程阻塞,B线程就绪,篮子里没鸡蛋时,A线程就绪,B线程阻塞,代码如下:
输出结果:
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
程序开始,A线程判断篮子是否为空,放入一个鸡蛋,并且唤醒在阻塞队列的一个线程,阻塞队列为空;假设CPU又调度了一个A线程,篮子非空,执行等待,这 个A线程进入阻塞队列;然后一个B线程执行,篮子非空,取走鸡蛋,并唤醒阻塞队列的A线程,A线程进入就绪队列,此时就绪队列就一个A线程,马上执行,放 入鸡蛋;如果再来A线程重复第一步,再来B线程重复第二步,整个过程就是生产者(A线程)生产鸡蛋,消费者(B线程)消费鸡蛋。
这个例子中,同步(互斥)的资源是一个实实在在的篮子对象,其实,共享资源也可以是一个简单的变量,如下面的例子,共享资源是一个bool变量。
例: 子线程循环10次,然后主线程循环100次,如此循环100次。子循环执行时主循环不能执行,主循环执行时子循环也不能执行。
需要注意的是,在上面的例子中,在调用wait方法时,都是用while判断条件的,而不是if,在wait方法说明中,也推荐使用while,因为在某些特定的情况下,线程有可能被假唤醒,使用while会循环检测更稳妥。
在很多情况下,多线程间仅仅同步是不够的,还需要线程与线程协作(通信),生产者/消费者模式是一个经典的线程同步以及通信的模型。
假设有这样一种情况,有一个篮子,篮子里只能放一个鸡蛋,A线程专门往篮子里放鸡蛋,如果篮子里有鸡蛋,则一直等到篮子里没鸡蛋,B线程专门从篮子里取鸡蛋,如果篮子里没鸡蛋,则一直等到篮子里有鸡蛋。这里篮子是一个互斥区,每次放鸡蛋是互斥的,每次取鸡蛋也是互斥的,A线程放鸡蛋,如果这时B线程要取鸡蛋,由于A没有释放锁,B线程处于等待状态,进入阻塞队列,放鸡蛋之后,要通知B线程取鸡蛋,B线程进入就绪队列,反过来,B线程取鸡蛋,如果A线程要放 鸡蛋,由于B线程没有释放锁,A线程处于等待状态,进入阻塞队列,取鸡蛋之后,要通知A线程放鸡蛋,A线程进入就绪队列。我们希望当篮子里有鸡蛋时,A线程阻塞,B线程就绪,篮子里没鸡蛋时,A线程就绪,B线程阻塞,代码如下:
/** * */ package com.wsheng.thread.communication; /** * 鸡蛋类 * * @author Wang Sheng(Josh) * */ public class Egg { private double weight; private double price; public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } } /** * */ package com.wsheng.thread.communication; import java.util.ArrayList; import java.util.List; /** * 线程间的通信: 放鸡蛋和取鸡蛋 - 生产者和消费者 * @author Wang Sheng(Josh) * */ public class Basket { /** 共享资源:篮子 */ private List<Egg> eggs = new ArrayList<Egg>(); /** 取鸡蛋*/ public synchronized Egg getEgg() { while (eggs.size() == 0) { try { wait(); // 当前线程进入阻塞队列 } catch (InterruptedException e) { e.printStackTrace(); } } Egg egg = eggs.get(0); // 清空篮子 eggs.clear(); // 唤醒阻塞队列的某线程到就绪队列 notify(); System.out.println("拿到鸡蛋"); return egg; } /** 放鸡蛋 */ public synchronized void putEgg(Egg egg) { while (eggs.size() > 0) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } eggs.add(egg); // 唤醒阻塞队列的某线程到就绪队列 notify(); System.out.println("放入鸡蛋"); } static class PutThread extends Thread { private Basket basket; private Egg egg = new Egg(); public PutThread(Basket basket) { this.basket = basket; } public void run() { basket.putEgg(egg); } } static class GetThread extends Thread { private Basket basket; public GetThread(Basket basket) { this.basket = basket; } public void run() { basket.getEgg(); } } public static void main(String[] args) { Basket basket = new Basket(); for (int i = 0; i < 10; i++) { new PutThread(basket).start(); new GetThread(basket).start(); } } }
输出结果:
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
放入鸡蛋
拿到鸡蛋
程序开始,A线程判断篮子是否为空,放入一个鸡蛋,并且唤醒在阻塞队列的一个线程,阻塞队列为空;假设CPU又调度了一个A线程,篮子非空,执行等待,这 个A线程进入阻塞队列;然后一个B线程执行,篮子非空,取走鸡蛋,并唤醒阻塞队列的A线程,A线程进入就绪队列,此时就绪队列就一个A线程,马上执行,放 入鸡蛋;如果再来A线程重复第一步,再来B线程重复第二步,整个过程就是生产者(A线程)生产鸡蛋,消费者(B线程)消费鸡蛋。
这个例子中,同步(互斥)的资源是一个实实在在的篮子对象,其实,共享资源也可以是一个简单的变量,如下面的例子,共享资源是一个bool变量。
例: 子线程循环10次,然后主线程循环100次,如此循环100次。子循环执行时主循环不能执行,主循环执行时子循环也不能执行。
/** * */ package com.wsheng.thread.synchronize; /** * @author Wang Sheng(Josh) * */ public class LoopThreadTest { public static void main(String[] args) { final Loop loopObj = new Loop(); new Thread(new Runnable() { public void run() { execute(loopObj, "sub"); } }).start(); execute(loopObj, "main"); } public static void execute(Loop loop, String threadType) { for (int i = 0; i < 100; i++) { try { if ("main".equals(threadType)) { loop.mainThread(i); } else { loop.subThread(i); } } catch (InterruptedException e) { e.printStackTrace(); } } } } class Loop { private boolean isSubThread = true; public synchronized void mainThread(int loop) throws InterruptedException { while (isSubThread) { this.wait(); } for (int i = 0; i < 100; i++) { System.out.println("main thread sequence of " + i + ", loop of " + loop); } isSubThread = true; // 主线程执行完毕,由子线程来执行 this.notify(); // 唤醒阻塞队列中的子线程到就绪队列 } public synchronized void subThread(int loop) throws InterruptedException { while (!isSubThread) { this.wait(); } for (int i = 0; i < 10; i++) { System.out.println("sub thread sequence of " + i + ", loop of " + loop); } isSubThread = false; // 子线程执行完毕,由主线程来执行 this.notify(); // 唤醒阻塞队列中的主线程到就绪队列 } }
需要注意的是,在上面的例子中,在调用wait方法时,都是用while判断条件的,而不是if,在wait方法说明中,也推荐使用while,因为在某些特定的情况下,线程有可能被假唤醒,使用while会循环检测更稳妥。
发表评论
-
gradle编译错误:Could not find method compile() for arguments
2020-09-19 10:50 18477编译(IDEA+Gradle)一个别人的工程,出现一个 ... -
netty心跳检查之UDP篇
2019-09-15 08:50 2391部分UDP通信场景中,需要客户端定期发送心跳信息,以获取终 ... -
解决tomcat部署两个SpringBoot应用提示InstanceAlreadyExistsException
2019-06-30 11:49 3385两个SpringBoot应用部署在一个Tomcat中,单独 ... -
Eclipse配置MyBatis代码自动化功能
2019-06-29 10:16 17681.安装插件 Eclipse中,Help->Ecli ... -
vue.js中使用qrcode生成二维码
2019-05-20 00:00 7654一、安装包 npm install qrcodejs2 --s ... -
MySQL插入数据报错: Incorrect string value: '\xFD\xDE'
2019-03-31 23:19 1238我MySQL数据库用的uft-8字符集,插入数据一直很正常 ... -
vue自定义组件并双向绑定属性
2019-03-08 22:46 3255做了两个子组件,原理基本一样,一个是使用原生的select ... -
vue-router简单示例
2019-03-05 00:32 1150写个基本完整、稍有借鉴意义的示例,防止自己忘记。 &l ... -
“联通充值系统繁忙”轻松应对
2019-02-06 11:03 3973大过年的,联通充个值一直报“充值系统繁忙”。昨天晚上试了几 ... -
electron.js数据库应用---导航菜单(element-ui+mysql)
2019-02-05 21:33 2364一、环境搭建 略, ... -
electron.js数据库应用---入门(mysql+element-ui)
2019-01-27 23:19 7492我的机器:Windows10,64 ... -
SpringMVC 在controller层中注入成员变量request,是否线程安全
2018-12-17 21:17 2747@RestController public class ... -
VueJS 组件参数名命名与组件属性转化
2018-12-03 00:00 2073转自:https://www.cnblogs.com/meiy ... -
vue-resource拦截器实现token发送及检验自动化
2018-11-16 22:38 3077用了很长时间vue-resource,最近思考$http发 ... -
element-ui试用手记
2018-10-29 20:25 1742element-ui、iviewui都以vue.js为基础 ... -
iviewui中表格控件中render的使用示例
2018-07-07 16:46 9785示例了如何在表格中显示按钮,如何将代码转化为文字。 i ... -
Tomcat错误“Alias name tomcat does not identify a key entry”解决
2018-07-05 21:39 6565申请到了阿里云的证书后,下载、按照说明生成jks格式证书、 ... -
阿里云免费证书“fileauth.txt内容配置错误”解决
2018-07-05 20:43 5295最近研究微信小程序开发,上阿里云申请了个证书,使用文件验证 ... -
springboot2.0跨域配置
2018-07-04 22:11 5283springboot2.0跨域配置: 一、代码 ... -
微信小程序使用code换openid的方法(JAVA、SpringBoot)
2018-07-01 21:52 10398微信小程序序的代码中提示,使用code换取openid,但 ...
相关推荐
总的来说,Java的线程通信机制为多线程环境下的协作提供了基础。理解并正确使用`wait()`、`notify()`和`notifyAll()`,以及如何通过共享对象进行通信,是编写高效并发程序的关键。在实际编程中,应确保避免竞态条件...
### Java多线程—线程间的通信 #### 一、线程间的通信 ##### (1)为什么要处理线程间的通信? 在多线程环境中,不同的线程可能需要协同工作来完成一项任务。例如,一个线程负责生产数据,另一个线程负责消费这些...
### Java多线程知识点总结及企业真题解析 #### 一、知识点总结 ##### (1)多线程相关概念 1. **程序、进程和线程的区分**: - **程序**:为了完成特定的任务而编写的指令集合。它是静态的概念。 - **进程**:...
《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...
总结起来,“JAVA多线程编程技术PDF”涵盖了多线程的基本概念、同步机制、线程通信、死锁避免、线程池以及线程安全的集合类等内容。通过深入学习这份资料,开发者可以全面掌握Java多线程编程技术,提升程序的并发...
在本文中,我们将深入浅出Java多线程编程的世界,探索多线程编程的基本概念、多线程编程的优点、多线程编程的缺点、多线程编程的应用场景、多线程编程的实现方法等内容。 一、多线程编程的基本概念 多线程编程是指...
Java多线程下载器是一种利用Java编程语言实现的高效文件下载工具,它通过将大文件分割成多个部分并同时下载,显著提高了下载速度。在Java中实现多线程下载器涉及许多关键概念和技术,包括线程、并发控制、网络I/O...
书中详细介绍了Java多线程的核心概念,如线程的创建、启动、同步、协作以及生命周期管理。读者将学习如何通过实现Runnable接口或继承Thread类来创建线程,以及如何使用Executor框架来管理线程池。 此外,书中还深入...
7. **多线程与并发**:由于WebSocket连接是持久的,因此在处理大量并发连接时,需要考虑线程安全和性能优化。 8. **集成到Web应用**:Java WebSocket可以与Spring、Jersey等Web框架无缝集成,简化部署和管理。 ...
"Java多线程通信机制研究" Java多线程通信机制是Java程序设计中的一个复杂技术,涉及到...Java多线程通信机制是一个复杂的技术,需要深入了解Java多线程编程和通信机制的原理和实现方法,才能更好地应用于实际项目中。
总之,Java多线程是构建高性能并发应用的基础,理解并掌握线程的创建、同步、通信、协作模式以及异常处理,对于编写高效、稳定的Java程序至关重要。在实际开发中,结合Java提供的工具和设计模式,能够更好地解决多...
Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,提高了系统的效率和响应性。在Java中,多线程的实现主要通过两种方式:继承Thread类和实现Runnable接口。理解并掌握多线程的使用对于任何Java开发者...
在Java编程中,线程间通信(Inter-Thread Communication,简称ITC)是并发编程中的一个重要概念,它涉及...理解并熟练掌握回调以及其他线程通信机制是Java并发编程的关键,这对于开发高效、稳定的多线程应用至关重要。
- `wait()`, `notify()`, `notifyAll()`:基于对象监视器的线程通信,用于线程间的协作。 - `BlockingQueue`:一种高级的线程间通信方式,如`ArrayBlockingQueue`、`LinkedBlockingQueue`等。 5. **线程池**: -...
总之,Java多线程和异步调用是构建高效、响应迅速的应用程序的关键技术。通过合理利用这些工具和机制,开发者可以编写出能够充分利用多核处理器优势的代码,从而提高软件性能。在实际应用中,理解并熟练掌握这些概念...
在Java编程语言中,多线程是核心特性之一,它允许程序同时执行多个任务,从而提高了应用程序的效率和响应...文档“java多线程实例.docx”可能包含具体的示例代码和详细解释,建议参考学习,以加深对Java多线程的理解。
Java多线程是Java编程中的重要概念,尤其在开发高性能、高并发的应用中不可或缺。本示例旨在为初学者提供一个全面理解Java多线程的起点。通过学习这个实例,你可以掌握如何创建和管理线程,理解线程同步与通信的重要...
Java多线程是Java编程语言中的一个重要特性,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在现代计算机系统中,多核处理器的普及使得多线程技术成为提升性能的关键手段。本篇将深入探讨Java多线程...
线程同步机制包括`synchronized`、`wait()`、`notify()` 和 `notifyAll()` 等,它们用于控制线程间的协作和通信,防止数据竞争和死锁的发生。 此外,Java还提供了线程池(ThreadPool)来管理线程的生命周期,通过...