当前位置: 首页 > 编程日记 > 正文

java 线程通讯_java多线程(五)线程通讯

1.1. 为什么要线程通信

多个线程并发执行时,在默认情况下CPU是随机切换线程的,有时我们希望CPU按我们的规律执行线程,此时就需要线程之间协调通信。

1.2. 线程通讯方式

线程间通信常用方式如下:

l  休眠唤醒方式:

Object的wait、notify、notifyAll

Condition的await、signal、signalAll

l  CountDownLatch:用于某个线程A等待若干个其他线程执行完之后,它才执行

l  CyclicBarrier:一组线程等待至某个状态之后再全部同时执行

l  Semaphore:用于控制对某组资源的访问权限

1.2.1.   休眠唤醒方式

Object的wait、notify、notifyAll

package com.signal;/**

* @Auther: lanhaifeng

* @Date: 2019/11/21 0021 09:32

* @Description:使用Object类的通信

* @statement:*/

public classWaitNotifyRunnable {private Object obj = newObject();private Integer i=0;//单数

public voidodd() {while(i<10){

synchronized (obj){if(i%2 == 1){

System.out.println(Thread.currentThread().getName()+"【奇数】:"+i);

i++;

obj.notify();

}else{try{

obj.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

}//双数

public voideven(){while(i<10){

synchronized (obj){if(i%2 == 0){

System.out.println(Thread.currentThread().getName()+"【偶数】:"+i);

i++;

obj.notify();

}else{try{

obj.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

}//测试

public static voidmain(String[] args){

final WaitNotifyRunnable runnable= newWaitNotifyRunnable();

Thread t1= new Thread(newRunnable() {public voidrun() {

runnable.odd();

}

},"奇数线程");

Thread t2= new Thread(newRunnable() {public voidrun() {

runnable.even();

}

},"偶数线程");

t1.start();

t2.start();

}

}

运行效果:

410b62621dfaacaa010ce5f72afe7a9c.png

Condition的await、signal、signalAll

package com.signal;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;/**

* @Auther: lanhaifeng

* @Date: 2019/11/21 0021 09:39

* @Description:使用Condition的await、signal

* @statement:*/

public classAwaitSignalRunnable {private Lock lock = newReentrantLock();private Condition condition = lock.newCondition();private Integer i=0;public voidodd() {while(i<10){lock.lock();try{if(i%2 == 1){

System.out.println(Thread.currentThread().getName()+"【奇数】:"+i);

i++;

condition.signal();

}else{

condition.await();

}

}catch(InterruptedException e) {

e.printStackTrace();

}finally{lock.unlock();

}

}

}public voideven(){while(i<10){lock.lock();try{if(i%2 == 0){

System.out.println(Thread.currentThread().getName()+"【偶数】:"+i);

i++;

condition.signal();

}else{

condition.await();

}

}catch(InterruptedException e) {

e.printStackTrace();

}finally{lock.unlock();

}

}

}//测试

public static voidmain(String[] args){

final WaitNotifyRunnable runnable= newWaitNotifyRunnable();

Thread t1= new Thread(newRunnable() {public voidrun() {

runnable.odd();

}

},"奇数线程");

Thread t2= new Thread(newRunnable() {public voidrun() {

runnable.even();

}

},"偶数线程");

t1.start();

t2.start();

}

}

运行效果:

074da7aca1e281b664448a771585d1fe.png

Object和Condition休眠唤醒区别

l  object wait()必须在synchronized(同步锁)下使用,

l  object wait()必须要通过Nodify()方法进行唤醒

l  condition await() 必须和Lock(互斥锁/共享锁)配合使用

l  condition await() 必须通过 signal() 方法进行唤醒

1.2.2.   CountDownLatch方式

CountDownLatch是在java1.5被引入的,存在于java.util.concurrent包下。

CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。

CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。

e3a84c7f05694c764b0491fc60711943.png

每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

示例代码:

package com.signal;

import java.util.concurrent.CountDownLatch;/**

* @Auther: lanhaifeng

* @Date: 2019/11/21 0021 09:46

* @Description:使用CountDownLatch

* 每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

* @statement:*/

public classCountDown {private Integer i = 0;private CountDownLatch countDownLatch = new CountDownLatch(1);//奇数

public voidodd(){while(i <10){if(i%2 == 1){

System.out.println(Thread.currentThread().getName()+"【奇数】:"+i);

i++;

countDownLatch.countDown();

}else{try{

countDownLatch.await();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}//偶数

public voideven(){while(i <10){if(i%2 == 0){

System.out.println(Thread.currentThread().getName()+"【偶数】:"+i);

i++;

countDownLatch.countDown();

}else{try{

countDownLatch.await();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}//测试

public static voidmain(String[] args){

final CountDown countDown= newCountDown();

Thread t1= new Thread(newRunnable() {public voidrun() {

countDown.odd();

}

},"奇数");

Thread t2= new Thread(newRunnable() {public voidrun() {

countDown.even();

}

},"偶数");

t1.start();

t2.start();

}

}

执行效果:

73f11270f39503168ef01fe902aaf6aa.png

1.2.3.   CyclicBarrier方式

CyclicBarrier是在java1.5被引入的,存在于java.util.concurrent包下。

CyclicBarrier实现让一组线程等待至某个状态之后再全部同时执行。

CyclicBarrier底层是

三个线程同时启动,示例代码如下:

package com.signal;

import java.util.Date;

import java.util.concurrent.BrokenBarrierException;

import java.util.concurrent.CyclicBarrier;/**

* @Auther: lanhaifeng

* @Date: 2019/11/21 0021 09:52

* @Description:使用CyclicBarrier

* CyclicBarrier实现让一组线程等待至某个状态之后再全部同时执行。

* @statement:*/

public classCyclicBarrierDemo {public static voidmain(String[] args){

final CyclicBarrier cyclicBarrier= new CyclicBarrier(3);new Thread(newRunnable() {public voidrun() {

System.out.println(Thread.currentThread().getName()+":准备...");try{

cyclicBarrier.await();

}catch(InterruptedException e) {

e.printStackTrace();

}catch(BrokenBarrierException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"启动完毕:"+newDate().getTime());

}

},"线程1").start();new Thread(newRunnable() {public voidrun() {

System.out.println(Thread.currentThread().getName()+":准备...");try{

cyclicBarrier.await();

}catch(InterruptedException e) {

e.printStackTrace();

}catch(BrokenBarrierException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"启动完毕:"+newDate().getTime());

}

},"线程2").start();new Thread(newRunnable() {public voidrun() {

System.out.println(Thread.currentThread().getName()+":准备...");try{

cyclicBarrier.await();

}catch(InterruptedException e) {

e.printStackTrace();

}catch(BrokenBarrierException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+"启动完毕:"+newDate().getTime());

}

},"线程3").start();

}

}

执行效果如下:三个线程同时启动

5d5f361e3be8e72793720b68ee984437.png

1.2.4.   Semaphore方式

Semaphore是在java1.5被引入的,存在于java.util.concurrent包下。

Semaphore用于控制对某组资源的访问权限。

工人使用机器工作,示例代码如下:

package com.signal;

import java.util.concurrent.Semaphore;/**

* @Auther: lanhaifeng

* @Date: 2019/11/21 0021 09:56

* @Description: 使用Semaphore

* emaphore用于控制对某组资源的访问权限

* @statement:*/

public classSemaphoreDemo {static classMachine implements Runnable{private int num;//工号

privateSemaphore semaphore;public Machine(intnum, Semaphore semaphore) {this.num =num;this.semaphore =semaphore;

}public voidrun() {try{

semaphore.acquire();//请求机器

System.out.println("工人"+this.num+"请求机器,正在使用机器");

Thread.sleep(1000);

System.out.println("工人"+this.num+"使用完毕,已经释放机器");

semaphore.release();//释放机器

} catch(InterruptedException e) {

e.printStackTrace();

}

}

}public static voidmain(String[] args){int worker = 8;//工人数

Semaphore semaphore = new Semaphore(3);//机器数

for (int i=0; i< worker; i++){new Thread(newMachine(i, semaphore)).start();

}

}

}

执行效果如下:

b0f5b4bc6ee1d1a6fa020a89bfafb40d.png

1.3. 小结

1.3.1.   sleep和wait区别

8354263356310ee7761aa980eca8d0e1.png

1.3.2.   wait和notify区别

wait和notify都是Object中的方法

wait和notify执行前线程都必须获得对象锁

wait的作用是使当前线程进行等待

notify的作用是通知其他等待当前线程的对象锁的线程

相关文章:

合并排序(C语言实现)

递归算法是把一个问题分解成和自身相似的子问题&#xff0c;然后再调用自身把相应的子问题解决掉。这些算法用到了分治思想。其基本模式如下&#xff1a; 分解&#xff1a;把一个问题分解成与原问题相似的子问题 解决&#xff1a;递归的解各个子问题 合并&#xff1a;合并子问题…

工程实践也能拿KDD最佳论文?解读Embeddings at Airbnb

作者 | Mihajlo Grbovic&#xff0c;Airbnb 资深机器学习科学家译者 | Lang Yang&#xff0c;Airbnb 工程经理【导读】本文最早于 2018 年 5 月 13 日发表&#xff0c;主要介绍了机器学习的嵌入技术在 Airbnb 爱彼迎房源搜索排序和实时个性化推荐中的实践。Airbnb 爱彼迎的两位…

计算点、线、面等元素之间的交点、交线、封闭区域面积和闭合集(续1)

继续上一节的内容&#xff0c;本节主要讲解三维空间中射线、线段与平面及三维物体的交点及距离的计算&#xff0c;它们在碰撞检测和可见性剔除等应用中是必不可少的。首先给出3D空间下点乘和叉乘的定义与定理的推导&#xff0c;再谈如何应用到程序编码的工作中。 设三维空间中任…

android 抓取native层奔溃

使用android的breakpad工具 使用这个工具需要下载Breakpad的源码&#xff0c;然后进行编译&#xff0c;编译之后会生成两个工具 我们使用这两个工具来解析奔溃的位置。这里我们可以下载已经编译好的工具 下载地址是&#xff1a;链接&#xff1a;http://pan.baidu.com/s/1jIiU5c…

渗透各行各业,这家RPA外企宣布全面进军中国市场

11月15日&#xff0c;全球机器人流程自动化&#xff08;RPA&#xff09;领域平台UiPath首次在中国举办UiPath Together年度大会&#xff0c;来自自动化、人工智能和机器学习领域的行业专家&#xff0c;以及来自中国和世界的领先公司的客户与合作伙伴共同参与了此次活动。在此次…

java gettext_JAVA中getText()怎么从一个JTextArea中读出内容?

想先创建一个JTextArea&#xff0c;然后在里面输入内容(几个字母)&#xff0c;然后用getText读出里面的内容&#xff0c;可是好像只能是先在JTextArea里面写&#xff0c;然后getText才能读出&#xff0c;而不能先运行&#xff0c;在图形界面的JTex...想先创建一个JTextArea&…

想在SqlDbHelper.cs类中加的垃圾方法

虽然没改写SqlDbHelper.cs类的能力&#xff0c;但好不容易想出来的&#xff0c;放着留个纪念~~~~~/**//// <summary> /// 执行SQL语句&#xff0c;返回第一行&#xff0c;第一列&#xff08;sea&#xff09; /// </summary> /// <param na…

java全站_javaWeb_全站编码

目的 : 实现javaweb项目的全站编码问题需要解决的问题 : 在何时进行编码问题的解决, 在何处进行编码问题的解决, 才用什么方法进行解决设计思路 : 在Filter进行全站的编码转换, 对于GET请求 : 使用装饰者模式(是你有你一切拜托你), 修改Request.getParameter()方法, 在getparam…

在Linux系统中修改目录的权限如何恢复

在我工作中的某一天执行了chmod -R 777 /home后我十分后悔&#xff0c;这下不知道该怎么办&#xff1f;心里面很是着急。此时灵机一动问了一下谷哥&#xff0c;终于找到了方法解决此问题&#xff0c;不过前提是要自己做了文件权限备份工作&#xff0c;现在我就给大家讲解一下我…

.Net Framework 3.5 结构图

从打印社用A0或A1的纸打出来&#xff0c;大概10RMB&#xff0c;看起来超爽。 转载于:https://www.cnblogs.com/habin/archive/2008/03/15/1107196.html

关于CVPR 2019投稿的一些感想

作者 | 胡国圣&#xff0c;英国 anyvision 高级研究员&#xff0c;从事深度学习&#xff0c;人脸识别的研究。一年一度的 CVPR 是人工智能的机器视觉方向最重要的学术会议&#xff0c;每年吸引都会全球最顶尖的大学和公司的研究人员投稿&#xff0c;文章如果被录用&#xff0c;…

ORACLE 数据泵导入导出数据

一、摘要 在平常备库和数据库迁移的时候&#xff0c;当遇到大的数据库的时候在用exp的时候往往是需要好几个小时&#xff0c;耗费大量时间。oracle10g以后可以用expdp来导出数据库花费的时间要远小于exp花费的时间&#xff0c;而且文件也要小很多。 二、exp/imp与expdp/impdp区…

java备忘录模式应用场景_图解Java设计模式之备忘录模式

图解Java设计模式之备忘录模式游戏角色状态恢复问题游戏角色有攻击力和防御力&#xff0c;在大战Boss前保存自身的状态(攻击力和防御力)&#xff0c;当大战Boss后攻击力和防御力下降&#xff0c;从备忘录对象恢复到大战前的状态。传统方案解决游戏角色恢复传统的方式的问题分析…

一文掌握常用的机器学习模型(文末福利)

AI 科技大本营按&#xff1a;本文节选自微软亚洲研究院机器学习研究团队刘铁岩、陈薇、王太峰、高飞合著的《分布式机器学习&#xff1a;算法、理论与实践》一书。为了让大家更好地理解分布式机器学习&#xff0c;AI科技大本营联合华章科技特别邀请到了本书的作者之一——微软亚…

MYSQL替换语句

update dede_art set titlereplace(title, <IMG border0 srcImages/hot.gif>,);update 表名(比如我案例中的dede_art) set 要修改字段名 replace (要修改字段名,被替换的特定字符,替换成的字符) SELECT * FROM supe_spaceitems where subject like %狐狸天空% update …

phpstudy+phpstorm+debug

文:phpstudyphpstormdebug 一、配置前说明&#xff1a; 1、phpStudy集成了XDebug扩展&#xff0c;所以不用单独下载XDebug。 2、打开XDebug扩展&#xff1a;其它选项菜单 > PHP扩展 > Xdebug 二、配置步骤&#xff1a; 1、phpStudy当前版本&#xff1a; 2、修改php.ini…

java 卖票问题_Java之多线程窗口卖票问题(Thread)

/**** 例子&#xff1a;创建三个窗口卖票&#xff0c;总票数为100张.使用继承Thread类的方式** 存在线程的安全问题&#xff0c;待解决。**/class Window extends Thread{private static int ticket 100;Overridepublic void run() {while(true){if(ticket > 0){System.out…

雷军深情告白:在我心里,武汉大学是全球最好的大学

武汉大学将在 11 月 29 迎来 125 周年校庆&#xff0c;作为杰出校友&#xff0c;小米创始人雷军参加了昨天举行的第五届校友珞珈论坛。现场&#xff0c;雷军对武大深情表白&#xff1a;“马云在几个场合说过&#xff0c;杭州师范大学在他心里是全球最好的大学&#xff0c;没有之…

java中抽象接口_一篇文章让你彻底理解java中抽象类和接口

相信大家都有这种感觉&#xff1a;抽象类与接口这两者有太多相似的地方&#xff0c;又有太多不同的地方。往往这二者可以让初学者摸不着头脑&#xff0c;无论是在实际编程的时候&#xff0c;还是在面试的时候&#xff0c;抽象类与接口都显得格外重要&#xff01;希望看完这篇博…

linux proc

/proc文件系统下的多种文件提供的系统信息不是针对某个特定进程的&#xff0c;而是能够在整个系统范围的上下文中使用。可以使用的文件随系统配置的变化而变化。 /proc/cmdline 这个文件给出了内核启动的命令行。 /proc/cpuinfo 这个文件提供了有关系统CPU的多种信息。 /proc/d…

专访英特尔AIPG全球研究负责人Casimir Wierzynski:物理学、隐私和大脑将根本性塑造AI

出品| AI 科技大本营 在 11 月 14 日至 15 日在北京召开的英特尔人工智能大会&#xff08;AIDC&#xff09;上&#xff0c;英特尔人工智能产品事业部&#xff08;AIPG&#xff09;全球研究负责人 Casimir Wierzynski 发表了主题为《人工智能研究——物理学、隐私和大脑》的演讲…

微软OOXML申请国际文档标准已获通过 中国投反对票

51CTO.com北京时间3月28日中午通过消息灵通人士获悉&#xff0c;微软新一代文档标准OOXML已经获得国际标准化组织&#xff08;ISO&#xff09;的通过。中国依然投反对票。 ISO共有104个成员&#xff0c;其中包括41个技术能力强、参与标准化活动多的“P成员”。若微软文档标准想…

java中的匿名类方法覆盖_Java技巧:用匿名类来实现简化程序调试

Java技巧&#xff1a;用匿名类来实现简化程序调试在Java中&#xff0c;匿名类(Anonymous inner classes)多用来处理事件(event handle)。但其实&#xff0c;它们对于debug也很有帮助。本文将介绍如何利用匿名类来简化你的debug。我们该如何调试那些非自己源码的方法调用呢&…

记录第一次在egret项目中使用Puremvc

这几天跟着另一个前端在做一个小游戏&#xff0c;使用的是egret引擎和puremvc框架&#xff0c;这对于我来说还是个比较大的突破吧&#xff0c;特此记录下。 因为在此项目中真是的用到了mvc及面向对象编程&#xff0c;值得学习 记录第一次在egret项目中使用Puremvc&#xff1a; …

使用CSS制作圆角效果

Web2.0中&#xff0c;圆角效果是很常见的&#xff0c;以前都是用图片来模仿&#xff0c;现在直接用css就能实现&#xff0c;例子代码如下 Html代码&#xff1a; <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> &…

知识图谱升温之势已现,不要错失下一个AI风口

近年来&#xff0c;随着大家对高级认知能力的积极探索&#xff0c;知识图谱因为表达能力强&#xff0c;扩展性好&#xff0c;并能兼顾人类认知与机器自动处理&#xff0c;引起了学术界、工业界以及政府部门的高度关注。 最先被大家熟知的应用领域应属搜索引擎&#xff0c;为了…

干货 | 谷歌BERT模型fine-tune终极实践教程

作者 | 奇点机智从11月初开始&#xff0c;Google Research就陆续开源了BERT的各个版本。Google此次开源的BERT是通过TensorFlow高级API—— tf.estimator进行封装(wrapper)的。因此对于不同数据集的适配&#xff0c;只需要修改代码中的processor部分&#xff0c;就能进行代码的…

java简介 ppt 精_《JAVA》5选择结构精篇课件.ppt

《JAVA》5选择结构精篇课件选 择 结 构 if 语句 if – else语句 Switch语句 块作用域语句又被称为复合语句&#xff0c;其格式为&#xff1a;用一对花括号将若干条语句括起来&#xff0c;目的是从语法上可以将多条语句解释成一条语句。 { int temp; temp a; a b; …

UPDATE STATISTICS 有何妙用?

txlicenhe 马可 一直没有关注它&#xff0c;今天刚学到的一招&#xff0c;还没彻底弄清楚。 情况是这样&#xff0c;有一个视图&#xff0c;用到了好几个表&#xff0c;其中一个表改了一些资料&#xff0c;在前台操作时总是超时过期&#xff08;前台设置超时时间不长 60s&#…

js with用法

1&#xff09;简要说明 with 语句可以方便地用来引用某个特定对象中已有的属性&#xff0c;但是不能用来给对象添加属性。要给对象创建新的属性&#xff0c;必须明确地引用该对象。 2&#xff09;语法格式 with(object instance) { //代码块 } 有…