本文章内容整理自:张孝祥_Java多线程与并发库高级应用视频教程。

有些时候,线程间需要传递消息,比如下面这道面试题:

子线程循环10次,然后主线程循环100次,然后又回到子线程循环50次,然后再回到主线程循环100次。以上过程一共循环50次。

通过分析可以知道,主线程和子线程是互斥的,即主线程和子线程不能同时执行。此外,主线程和子线程有固定的轮换关系,主线程执行完后,必须是子线程接着执行,然后又是主线程执行。

要达到这种效果,光是线程互斥是不够的。因为有可能主线程执行完之后,cpu又将执行的权利分配给主线程,这样主线程又会执行一遍。要让两个线程交替执行,就需要这两个线程间可以通信。主线程执行完了,就通知子线程执行。子线程执行完了,再通知主线程执行。如此往复。

像这种线程间协作的情况,就叫线程同步。

下面直接贴出代码

package com.sky.thread;

public class Test4 {
private boolean mainOrSub = true;//线程间通信的变量
public static void main(String[] args) {
final Test4 t4 = new Test4();
new Thread(new Runnable() { @Override
public void run() {
//执行50次主线程
for (int i = 0; i < 50; i++) {
try {
t4.mainThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() { @Override
public void run() {
//执行50次子线程
for (int i = 0; i < 50; i++) {
try {
t4.subThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}).start();
} //主线程执行的方法
public synchronized void mainThread() throws InterruptedException {
//判断是否轮到自己执行
//此处用while代替if,可以提高程序的健壮性。
//线程有时会自己醒来,如果用if,当线程自己醒来后会接着执行this.wait()后面的代码,这样是不对的。
//而使用while,线程自己醒来后,根据while的规则,会再判断一次mainOrSub的值。
if (mainOrSub) {
//如果mainOrSub是true,表示不该自己执行。于是把线程挂起。
this.wait();
}
for (int i = 0; i < 100; i++) {
System.out.println("main-"+Thread.currentThread().getName() + ":" + i);
}
//执行完毕后更改mainOrSub的状态,并唤醒其他线程
mainOrSub = true;
this.notify();
} //子线程执行的方法
public synchronized void subThread() throws InterruptedException {
//判断是否轮到自己执行
while (!mainOrSub) {
//如果mainOrSub是false,表示不该自己执行。于是把线程挂起。
this.wait();
}
for (int i = 0; i < 10; i++) {
System.out.println("sub-"+Thread.currentThread().getName() + ":" + i);
}
//执行完毕后更改mainOrSub的状态,并唤醒其他线程
mainOrSub = false;
this.notify();
}
}

在上面的代码中,创建了一个变量mainOrSub用于线程间通信。通过mainOrSub的值来控制线程的交替执行。

可见,使用多个线程都可以访问到的变量,就可以实现线程间通信。

还有一点值得注意,在判断mainOrSub的值时,用while代替了if,这样可以提高程序的健壮性。因为使用wait()挂起的线程有时会自己醒来。如果用if,当线程自己醒来后会接着执行this.wait()后面的代码,而此时并不该它执行。如果用while,线程自己醒来后,根据while的规则,会再判断一次mainOrSub的值,这样就可以保证线程完全依照mainOrSub的值来决定要不要执行。

经验:要用到共同数据(包括同步锁)的若干个方法应该归在同一个类身上,这种设计体现了高内聚和程序的健壮性。

java多线程与线程并发三:线程同步通信的更多相关文章

  1. Java多线程基础:进程和线程之由来

    转载: Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够 ...

  2. Java多线程学习(八)线程池与Executor 框架

    目录 历史优质文章推荐: 目录: 一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 2.3 Executor 框架的使用示意图 ...

  3. Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier

    Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...

  4. 1、Java多线程基础:进程和线程之由来

    Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ...

  5. Java 多线程基础(四)线程安全

    Java 多线程基础(四)线程安全 在多线程环境下,如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线 ...

  6. Java 多线程基础(五)线程同步

    Java 多线程基础(五)线程同步 当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题. 要解决上述多线程并发访问一个资源的安全性问题,Java中提供了同步机制 ...

  7. Java 多线程基础(十一)线程优先级和守护线程

    Java 多线程基础(十一)线程优先级和守护线程 一.线程优先级 Java 提供了一个线程调度器来监控程序启动后进去就绪状态的所有线程.线程调度器通过线程的优先级来决定调度哪些线程执行.一般来说,Ja ...

  8. Java 多线程基础(六)线程等待与唤醒

    Java 多线程基础(六)线程等待与唤醒 遇到这样一个场景,当某线程里面的逻辑需要等待异步处理结果返回后才能继续执行.或者说想要把一个异步的操作封装成一个同步的过程.这里就用到了线程等待唤醒机制. 一 ...

  9. Java 多线程基础(七)线程休眠 sleep

    Java 多线程基础(七)线程休眠 sleep 一.线程休眠 sleep sleep() 方法定义在Thread.java中,是 static 修饰的静态方法.sleep() 的作用是让当前线程休眠, ...

  10. Java 多线程基础(八)线程让步

    Java 多线程基础(八)线程让步 yield 一.yield 介绍 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权:但是,并 ...

随机推荐

  1. 「看完不后悔系列!」Maya的建模小技巧

    Maya 将最大的联合影响力降至最低 最大的联合影响力是游戏角色装备的已知要求. 但是,对于每种类型的生产来说,这实际上都是一个很好的工作流程. 从透视图上看,如果你将联合影响力从4更改为5,则不一定 ...

  2. 机器学习:IB1算法的weka源码详细解析(1NN)

    机器学习的1NN最近邻算法,在weka里叫IB1,是因为Instance Base  1 ,也就是只基于一个最近邻的实例的惰性学习算法. 下面总结一下,weka中对IB1源码的学习总结. 首先需要把 ...

  3. css div 自适应内容

    .adapt-content{ display:inline-block; *display:inline; ; } 见:http://www.cnblogs.com/refe/p/5051661.h ...

  4. 在Ubuntu16.0.4安装hipcaffe

    1. 安装 AMD ROCm 显卡条件 要安装AMD的 ROCm显卡,必须满足以下条件,只能高于下面信息版本,不能低于. Distribution Kernel GCC GLIBC x86_64 Fe ...

  5. NServiceBus+Saga开发分布式应用

    前言       当你在处理异步消息时,每个单独的消息处理程序都是一个单独的handler,每个handler之间互不影响.这时如果一个消息依赖另一个消息的状态呢? 这时业务逻辑怎么处理?       ...

  6. .NET Core3.0创建Worker Services

    .NET CORE 3.0新增了Worker Services的新项目模板,可以编写长时间运行的后台服务,并且能轻松的部署成windows服务或linux守护程序.如果安装的vs2019是中文版本,W ...

  7. vue —— 监听

    vue的监听用途很大 比如:通过数据的值的变化,执行某个方法 首先:data中要有个变量初始值 finalTotalAmount的初始值是0 我们想当finalTotalAmount值发生变化时,执行 ...

  8. selenium-显式等待与隐式等待(3)

    示例代码: from selenium.webdriver.support.wait import WebDriverWait as WD def find_element(self, by, loc ...

  9. Redis 集群搭建(基于Linux)

    一.基础环境 1.虚拟机 VMware 15.x 2.Linux系统,用的是Centos7的Linux系统 3.Redis数据库版本 5.0.3 二.Redis集群简介 1.背景 Redis在3.0版 ...

  10. 程序员修神之路--为什么有了SOA,我们还用微服务?

    菜菜哥,我最近需要做一个项目,老大让我用微服务的方式来做 那挺好呀,微服务现在的确很流行 我以前在别的公司都是以SOA的方式,SOA也是面向服务的方式呀 的确,微服务和SOA有相同之处 面向服务的架构 ...