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()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权:但是,并 ...
随机推荐
- 《java编程思想》P125-P140(第七章复用类部分)
1.类的成员默认的是包访问权限.允许包内成员访问 2.super.scrub() 调用基类的scrub方法 3.继承并不是复制基类的接口.当创建了一个导出类(子类)对象时,该对象包含了一个基类的子对象 ...
- .Net Core3.0使用gRPC
gRPC是什么 gRPC是可以在任何环境中运行的现代开源高性能RPC框架.它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证.它也适用于分布式 ...
- 真——Springcloud支持Https
很久不写了,因为一直没有一个项目的需求推动,担心写的东西可能不是太实际.其间学习的事倒是做了不少,设计模式.领域开发.Antlr.kubernetes等等,其实大部分都记在纸质笔记上了.. 基于对新技 ...
- Vulnhub靶场渗透练习(一) Breach1.0
打开靶场 固定ip需要更改虚拟机为仅主机模式 192.168.110.140 打开网页http://192.168.110.140/index.html 查看源代码发现可以加密字符串 猜测base64 ...
- next day
#_*_coding:utf_*_#!/usr/bin/env python now_day=input('当前某一天:').format('%Y.%m.%d')%%输入日期(年.月.日) year= ...
- 非确定的自动机NFA确定化为DFA
摘要: 在编译系统中,词法分析阶段是整个编译系统的基础.对于单词的识别,有限自动机FA是一种十分有效的工具.有限自动机由其映射f是否为单值而分为确定的有限自动机DFA和非确定的有限自动机NFA.在非确 ...
- AJAX异步检查,检查用户名是否存在
AJAX异步检查,检查用户名是否存在 写法一: var xmlHttp; if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, ...
- spring cloud 2.x版本 Eureka Client服务提供者教程
本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 1 创建eureka client 1.1 新建Srping boot工程:eureka-c ...
- 第七篇 Flask实例化配置及Flask对象配置
一.Flask对象的配置 Flask 是一个非常灵活且短小精干的web框架 , 那么灵活性从什么地方体现呢? 有一个神奇的东西叫 Flask配置 , 这个东西怎么用呢? 它能给我们带来怎么样的方便呢? ...
- JVM垃圾收集策略与算法
垃圾收集策略与算法 程序计数器.虚拟机栈.本地方法栈随线程而生,也随线程而灭:栈帧随着方法的开始而入栈,随着方法的结束而出栈.这几个区域的内存分配和回收都具有确定性,在这几个区域内不需要过多考虑回收的 ...