java多线程与线程并发三:线程同步通信
本文章内容整理自:张孝祥_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多线程与线程并发三:线程同步通信的更多相关文章
- Java多线程基础:进程和线程之由来
转载: Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够 ...
- Java多线程学习(八)线程池与Executor 框架
目录 历史优质文章推荐: 目录: 一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 2.3 Executor 框架的使用示意图 ...
- Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...
- 1、Java多线程基础:进程和线程之由来
Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ...
- Java 多线程基础(四)线程安全
Java 多线程基础(四)线程安全 在多线程环境下,如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线 ...
- Java 多线程基础(五)线程同步
Java 多线程基础(五)线程同步 当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题. 要解决上述多线程并发访问一个资源的安全性问题,Java中提供了同步机制 ...
- Java 多线程基础(十一)线程优先级和守护线程
Java 多线程基础(十一)线程优先级和守护线程 一.线程优先级 Java 提供了一个线程调度器来监控程序启动后进去就绪状态的所有线程.线程调度器通过线程的优先级来决定调度哪些线程执行.一般来说,Ja ...
- Java 多线程基础(六)线程等待与唤醒
Java 多线程基础(六)线程等待与唤醒 遇到这样一个场景,当某线程里面的逻辑需要等待异步处理结果返回后才能继续执行.或者说想要把一个异步的操作封装成一个同步的过程.这里就用到了线程等待唤醒机制. 一 ...
- Java 多线程基础(七)线程休眠 sleep
Java 多线程基础(七)线程休眠 sleep 一.线程休眠 sleep sleep() 方法定义在Thread.java中,是 static 修饰的静态方法.sleep() 的作用是让当前线程休眠, ...
- Java 多线程基础(八)线程让步
Java 多线程基础(八)线程让步 yield 一.yield 介绍 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权:但是,并 ...
随机推荐
- django渲染高阶
08.16自我总结 django渲染高阶 一.利用母版渲染 1.创建母版文件 如:stamper.html <!DOCTYPE html> <html lang="en&q ...
- 代码审计-EasyCMS
cms来源AWD线下攻防平台题目. 链接:https://pan.baidu.com/s/1eUkyRspQmsv-0fIBby8ZlQ 提取码:tywa 失效可以联系我 0x01 文件上传漏 ...
- JavaScript回调函数和递归函数
一.回调函数--通过函数的指针来调用函数 把一个函数的指针作为另一个函数的参数,当调用这个参数的时候,这个函数就叫做回调函数 在链式运动上会用到回调函数,之后运动会见到 A.通过指针来调用函数 B.通 ...
- iguana::json/xml 序列化框架
环境:win10 vs2017 c++17 boost 1.下载源码:https://github.com/qicosmos/iguana 2.创建工程,包含源码目录.boost库目录:boos ...
- Spring Cloud Alibaba (nacos 注册中心搭建)
[nacos下载地址](https://github.com/alibaba/nacos/releases) ### 什么是 Nacos? - nacos主要起到俩个作用一个是注册中心,另外一个是配置 ...
- 浅谈线段树 Segment Tree
众所周知,线段树是algo中很重要的一项! 一.简介 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在 ...
- Mongoose-modified-at 时间自动记录插件介绍
Mongoose-modified-at 是一款自动更新字段变化时间并记录到数据库中的 Mongoose 插件,类似 Mongoose 自带的 timestamps 功能. 使用场景 让我们考虑一个场 ...
- 让button的文字换行和左对齐
btn.titleLabel.numberOfLines = 0; btn.contentHorizontalAlignment = UIControlContentHorizontalAlign ...
- Java自动化测试框架-04 - 来给你的测试报告化个妆整个形 - (上)(详细教程)
简介 前边通过宏哥的讲解和分享想必小伙伴们和童鞋们都已经见过testng框架生成的测试报告,是不是它的样子和长相实在是不敢让大家伙恭维.那么今天宏哥就当一回美容师,由宏哥来给它美美容:当一回外科医生, ...
- hexo博客yili主题个性化自定义教程(1) ——借鉴中学习,初认yili主题
文章转载于:hexo博客yili主题个性化自定义教程(1) --借鉴中学习,初认yili主题 这个博客跌跌撞撞也弄了好多天了,由于Next主题不知道什么情况,被我玩坏了.所以换了一个主题. 大名鼎鼎的 ...