多线程间如何通信和共享数据,肯定好多小伙伴都不知道, 或者很久之前知道,现在已经忘却,现在我和大家一起复习一下。

一、线程间通信

1、线程间通信:A执行完,B才执行

/*** 线程间通信:A执行完,B才执行*/@Testpublic void bWaitA(){Thread A = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("A 开始工作!!");System.out.println("A 结束工作!!");}});Thread B = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("B 开始等待 A");try {A.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("B 开始工作!!");System.out.println("B 结束工作!!");}});B.start();A.start();}

2、A执行一部分,B执行完,A再执行剩下的部分

    /*** A执行一部分,B执行完,A再执行剩下的部分* A 1, B 1, B 2, B 3, A 2, A 3** 首先创建一个 A 和 B 共享的对象锁 lock = new Object();* 当 A 得到锁后,先打印 1,然后调用 lock.wait() 方法,交出锁的控制权,进入 wait 状态;* 对 B 而言,由于 A 最开始得到了锁,导致 B 无法执行;直到 A 调用 lock.wait() 释放控制权后, B 才得到了锁;* B 在得到锁后打印 1, 2, 3;然后调用 lock.notify() 方法,唤醒正在 wait 的 A;* A 被唤醒后,继续打印剩下的 2,3。*/@Testpublic void aWaitB() {Object lock = new Object();Thread A = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("A 等待锁");synchronized (lock) {System.out.println("A 获得锁");System.out.println("A 1");try {System.out.println("A wait 放弃锁控制权,等待再次获取锁控制权");lock.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("被唤醒,重新获取锁控制权");System.out.println("A 2");System.out.println("A 3");}}});Thread B = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("B 等待获取锁控制权");synchronized (lock) {System.out.println("B 获取锁控制权");System.out.println("B 1");System.out.println("B 2");System.out.println("B 3");System.out.println("B 执行完毕 调用 notiry 方法");lock.notify();}}});A.start();B.start();}

3、四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的

    /*** 四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的** CountdownLatch 来实现这类通信方式。它的基本用法是:* 创建一个计数器,设置初始值,CountdownLatch countDownLatch = new CountDownLatch(2);* 在 等待线程 里调用 countDownLatch.await() 方法,进入等待状态,直到计数值变成 0;* 在 其他线程 里,调用 countDownLatch.countDown() 方法,该方法会将计数值减小 1;* 当 其他线程 的 countDown() 方法把计数值变成 0 时,等待线程 里的 countDownLatch.await() 立即退出,继续执行下面的代码。** 执行过程:* 其实简单点来说,CountDownLatch 就是一个倒计数器,我们把初始计数值设置为3,* 当 D 运行时,先调用 countDownLatch.await() 检查计数器值是否为 0,若不为 0 则保持等待状态;* 当A B C 各自运行完后都会利用countDownLatch.countDown(),将倒计数器减 1,* 当三个都运行完后,计数器被减至 0;此时立即触发 D 的 await() 运行结束,继续向下执行。* 因此,CountDownLatch 适用于一个线程去等待多个线程的情况。*/@Testpublic void dWaitABC() {int worker = 3;CountDownLatch countDownLatch = new CountDownLatch(worker);new Thread(new Runnable() {@Overridepublic void run() {System.out.println("D 等待其他线程执行完毕");try {countDownLatch.await();System.out.println("所有需要等待的线程都执行完毕,D开始工作");} catch (InterruptedException e) {e.printStackTrace();}}}).start();for (char threadName='A'; threadName <= 'C'; threadName++) {final String threadNameStr = String.valueOf(threadName);new Thread(new Runnable() {@Overridepublic void run() {System.out.println(threadNameStr + " 正在工作");System.out.println(threadNameStr + " 工作完成");countDownLatch.countDown();}}).start();}}

4、个运动员各自准备,等到三个人都准备好后,再一起跑

    /***  三个运动员各自准备,等到三个人都准备好后,再一起跑** CyclicBarrier* 为了实现线程间互相等待这种需求,我们可以利用 CyclicBarrier 数据结构,它的基本用法是:* 先创建一个公共 CyclicBarrier 对象,设置 同时等待 的线程数,CyclicBarrier cyclicBarrier = new CyclicBarrier(3);* 这些线程同时开始自己做准备,自身准备完毕后,需要等待别人准备完毕,这时调用 cyclicBarrier.await(); 即可开始等待别人;* 当指定的 同时等待 的线程数都调用了 cyclicBarrier.await();时,意味着这些线程都准备完毕好,然后这些线程才 同时继续执行。*/@Testpublic void runABCWhenAllReady() {int runner = 3;CyclicBarrier cyclicBarrier = new CyclicBarrier(runner);final Random random = new Random();for (char runnerName='A'; runnerName <= 'C'; runnerName++) {final String runnerNameStr = String.valueOf(runnerName);new Thread(new Runnable() {@Overridepublic void run() {long prepareTime = random.nextInt(1000) + 100;System.out.println(runnerNameStr + " 线程正在做准备 " );try {Thread.sleep(prepareTime);} catch (Exception e) {e.printStackTrace();}try {System.out.println(runnerNameStr + " 线程准备完毕等待其他线程准备好");cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println("所有线程都准备好了,"+runnerNameStr +" 线程开始工作");}}).start();}// 让主线程休眠,让里面的线程执行完毕之前,主线程还存在try {Thread.sleep(60000);} catch (InterruptedException e) {e.printStackTrace();}}

二、线程数据共享

    /*** 线程间数据共享* 不同的线程,都有一个属性 ShareData ,并且线程的工作也封装 ShareData中。* 不同线程中的run方法执行的都是 ShareData 中指定的封装的方法*/@Testpublic void shareData(){ShareData shareData = new ShareData();for(int i=1;i<=2;i++){new Thread(new MyIncreRunnable(shareData)).start();new Thread(new MyDecreRunanble(shareData)).start();}}
    /*** 线程间数据共享* 不同的线程,都有一个属性 ShareData ,并且线程的工作也封装 ShareData中。* 不同线程中的run方法执行的都是 ShareData 中指定的封装的方法*/@Testpublic void shareData(){ShareData shareData = new ShareData();for(int i=1;i<=2;i++){new Thread(new MyIncreRunnable(shareData)).start();new Thread(new MyDecreRunanble(shareData)).start();}}class MyIncreRunnable implements Runnable{private ShareData shareData;public MyIncreRunnable(ShareData shareData) {this.shareData = shareData;}@Overridepublic void run() {for (int i = 1;i<=10;i++){shareData.increment();}}
}class MyDecreRunanble implements Runnable{private ShareData shareData;public MyDecreRunanble(ShareData shareData) {this.shareData = shareData;}@Overridepublic void run() {for(int i=1;i<=10;i++){shareData.decrement();}}
}/*** 共享数据,对共享数据的操作也在这个对象中完成*/
class ShareData{private int count = 0;public synchronized void increment(){count++;System.out.println(Thread.currentThread().getName()+" inc "+count);}public synchronized void decrement(){count--;System.out.println(Thread.currentThread().getName()+" dec " +count);}
}

Java多线程(Thread)间通信和共享数据相关推荐

  1. Java多线程多个线程之间共享数据

    线程范围的共享变量 多个业务模块针对同一个static变量的操作 要保证在不同线程中 各模块操作的是自身对应的变量对象 public class ThreadScopeSharaData {priva ...

  2. Java 如何线程间通信,面试被问哭。。。

    Java 如何线程间通信,曾经小编面试被问哭的一道题.. 正常情况下,每个子线程完成各自的任务就可以结束了.不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了. 本文涉及 ...

  3. 多线程-线程间通信-多生产者多消费者示例

    1.多线程-线程间通信-多生产者多消费者问题 多生产者和多消费者.等待唤醒机制. 产生了两个问题: 1.出现了多次连续生产,未消费,或者一个商品被消费多次. 解决:必须要--------每一个被唤醒的 ...

  4. Java多线程-Thread、Runnable、Executor

    线程分为五个阶段:创建.就绪.运行.阻塞.终止. 创建:新建一个线程对象,如Thread thd=new Thread(). 就绪:创建了线程对象后,调用了线程的start()方法(此时线程只是进入了 ...

  5. Java多线程之线程通信之生产者消费者阻塞队列版

    Java多线程之线程通信之生产者消费者传统版和阻塞队列版 目录 线程通信之生产者消费者传统版 线程通信之生产者消费者阻塞队列版 1. 线程通信之生产者消费者传统版 题目: 一个初始值为零的变量,两个线 ...

  6. 如何掌握java多线程,高并发,大数据方面的技能?

    https://www.zhihu.com/question/27575123 如何掌握java多线程,高并发,大数据方面的技能? 因为想进入互联网公司,然后发现互联网类型的公司问的主要问题都离不开这 ...

  7. Java多线程同步和通信

    多线程同步 回顾 1 进程:正在运行的程序,操作系统通过进程Id区分不同进程.2 线程:进程中的一条执行路径.一个进程中可以包含多个线程,至少有一个.3 区别:a.一个程序运行后至少有一个进程b.一个 ...

  8. Java多线程编程实战:模拟大量数据同步

    背景 最近对于 Java 多线程做了一段时间的学习,笔者一直认为,学习东西就是要应用到实际的业务需求中的.否则要么无法深入理解,要么硬生生地套用技术只是达到炫技的效果. 不过笔者仍旧认为自己对于多线程 ...

  9. Java并发——线程间通信与同步技术

    传统的线程间通信与同步技术为Object上的wait().notify().notifyAll()等方法,Java在显示锁上增加了Condition对象,该对象也可以实现线程间通信与同步.本文会介绍有 ...

最新文章

  1. Android Studio快捷键——编辑篇
  2. 使用sqoop将HIVE中的数据输出带Mysql中
  3. opencv 图像 抠图 算法_图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting
  4. mysql 创建表字段长度范围_老板要我把这份MySQL规范贴在工位上!
  5. RedisTemplate清空所有键值对
  6. 自动启动和关闭Oracle 脚本
  7. 【Ian Goodfellow 强推】GAN 进展跟踪 10 大论文(附下载)
  8. Hbase架构与实现
  9. NEFU计算机组成原理课程设计之乘法器
  10. 34.ADC基本原理与配置
  11. win10共享其它计算机文件,两台win10间如何文件共享
  12. 计算机公式求时间差公式,日期差计算(Excel表格中如何计算日期、时间差)
  13. css 实现心形加载动画
  14. Python — “输入直角边求斜边”
  15. 友盟QQ第三方登录分享
  16. 对SingleTask和TaskAffinity的理解
  17. 双11,客服系统让你告别客服节前emo
  18. 李开复给中国大学生的第三封信---成功、自信、快乐
  19. 针对firefox的恶意软件分析取证
  20. lol中国人最多的服务器,2021LOL哪个区人多_2021LOL服务器推荐

热门文章

  1. android有程序占用相机,Android相机 - 有时当我拍照时,应用程序冻结,相机不可用...
  2. python annotate函数_Matplotlib库 标注点函数annotate()
  3. Performance of Cell-Free Massive MIMO with Rician Fading and Phase Shifts (2)
  4. iconfont半月坑
  5. 《轩辕剑4》秘技小集
  6. Elasticsearch 入门 核心概念 数据结构 分词器 javaAPI
  7. Yii中Flash数据的处理机制(源码分析)
  8. day19Java-其它IO-Properties-属性集合类(可以结合IO)
  9. 使用BurnAware免费版轻松刻录光盘
  10. python123系统基本信息获取失败_交管123怎么总显示信息获取失败