Java多线程间通讯

多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。

1、使用wait()notify()方法在线程中通讯

需求:第一个线程写入(input)用户,另一个线程取读取(out)用户。实现写一个,读一个操作。

class User {
public String name;
public String sex;
// 读写标志(true:表示已经写入|false:表示未写入)
public boolean flag = false; @Override
public String toString() {
return "name:" + this.name + "=======" + "sex:" + this.sex;
}
} class InputThread extends Thread {
private User user; InputThread(User user) {
this.user = user;
} @Override
public void run() {
int count = 0;
while (true) {
synchronized (user) {
if (this.user.flag) {
try {
// 使当前线程等待
this.user.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count == 0) {
this.setVal("小红", "女");
} else {
this.setVal("小明", "男");
}
count = (count + 1) % 2; this.user.flag = true;
// 通知另一个线程解除等待状态,继续执行
this.user.notify();
}
}
} private void setVal(String name, String sex) {
this.user.name = name;
this.user.sex = sex;
} } class OutThread extends Thread { private User user; OutThread(User user) {
this.user = user;
} @Override
public void run() {
while (true) {
synchronized (user) {
if (!this.user.flag) {
try {
this.user.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.user.toString());
this.user.flag = false;
this.user.notify();
}
}
}
} public class ThreadCommDemo {
public static void main(String[] args) {
User user = new User();
InputThread inputThread = new InputThread(user);
OutThread outThread = new OutThread(user);
inputThread.start();
outThread.start();
} }

wait()notify()notifyAll()是三个定义在Object类中的方法,可以用来控制线程的状态。

①如果对象调用了wait()方法,就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态;

②如果对象调用了notify()方法,就会通知某个正在等待这个对象控制权的线程,可以继续运行;

③如果对象调用了notifyAll()方法,就会通知所有正在等待这个对象控制权的线程,可以继续运行。

wait()sleep()的区别

sleep()方法属于Thread类中,wait()方法属于Object类中。sleep()方法导致程序暂停执行指定的时间,让出cpu给其他线程,但是监控状态依然保持,当指定的时间到了之后又会自动恢复运行状态。

在调用sleep()方法的过程中,线程不会释放对象锁。

调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备,获取对象锁后进入运行状态。

注意:wait()方法需要包裹在同步块中

2、使用conditionawait()signal()方法在线程中通讯

class User01 {
public String name;
public String sex;
// 读写标志(true:表示已经写入|false:表示未写入)
public boolean flag = false; public Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); @Override
public String toString() {
return "name:" + this.name + "=======" + "sex:" + this.sex;
}
} class InputThread01 extends Thread {
private User01 user; InputThread01(User01 user) {
this.user = user;
} @Override
public void run() {
int count = 0;
while (true) {
this.user.lock.lock();
if (this.user.flag) {
try {
// 使当前线程等待
this.user.condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count == 0) {
this.setVal("小红", "女");
} else {
this.setVal("小明", "男");
}
count = (count + 1) % 2; this.user.flag = true;
// 通知另一个线程解除等待状态,继续执行
this.user.condition.signal();
this.user.lock.unlock();
}
} private void setVal(String name, String sex) {
this.user.name = name;
this.user.sex = sex;
} } class OutThread01 extends Thread { private User01 user; OutThread01(User01 user) {
this.user = user;
} @Override
public void run() {
while (true) {
this.user.lock.lock();
if (!this.user.flag) {
try {
this.user.condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.user.toString());
this.user.flag = false;
this.user.condition.signal();
this.user.lock.unlock();
}
}
} public class ThreadCommDemo01 {
public static void main(String[] args) {
User01 user = new User01();
InputThread01 inputThread = new InputThread01(user);
OutThread01 outThread = new OutThread01(user);
inputThread.start();
outThread.start();
}
}

condition.await()方法类似wait()方法,condition.signal()方法类似notify()方法。

源码地址

(Java多线程系列三)线程间通讯的更多相关文章

  1. Java多线程系列--“JUC线程池”04之 线程池原理(三)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...

  2. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  3. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  4. Java多线程系列--“JUC线程池”05之 线程池原理(四)

    概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...

  5. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

  6. java多线程系列(三)---等待通知机制

    等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...

  7. java多线程系列(六)---线程池原理及其使用

    线程池 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线程系列(三)之等待通知 ...

  8. Java多线程系列--“JUC线程池”01之 线程池架构

    概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容——线程池.内容包括:线程池架构 ...

  9. Java多线程编程(6)--线程间通信(下)

      因为本文的内容大部分是以生产者/消费者模式来进行讲解和举例的,所以在开始学习本文介绍的几种线程间的通信方式之前,我们先来熟悉一下生产者/消费者模式.   在实际的软件开发过程中,经常会碰到如下场景 ...

随机推荐

  1. 手写Spring MVC

    闲及无聊 又打开了CSDN开始看一看有什么先进的可以学习的相关帖子,这时看到了一位大神写的简历装X必备,手写Spring MVC. 我想这个东西还是有一点意思的 就拜读了一下大佬的博客 通读了一遍相关 ...

  2. Django2.1 authenticate 会关联数据库 is_active 的解决办法

    # 会检测用户是否是活跃状态(is_active),不活跃则返回None(默认配置)AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.M ...

  3. # Doing homework again(贪心)

    # Doing homework again(贪心) 题目链接:Click here~~ 题意: 有 n 门作业,每门作业都有自己的截止期限,当超过截止期限还没有完成作业,就会扣掉相应的分数.问如何才 ...

  4. 2019中山纪念中学夏令营-Day4[JZOJ]

    Begin (题目的排序方式:难易程度) 什么是对拍: 对拍是一种在写完程序后,验证自己程序是不是正解的比较方便的方法. 实现过程: 对同一道题,再打一个暴力程序,然后用一些大数据等跑暴力程序来进行验 ...

  5. 哈希表(Hash table)

  6. Hadoop大数据平台入门——HDFS和MapReduce

    随着硬件水平的不断提高,需要处理数据的大小也越来越大.大家都知道,现在大数据有多火爆,都认为21世纪是大数据的世纪.当然我也想打上时代的便车.所以今天来学习一下大数据存储和处理. 随着数据的不断变大, ...

  7. python之排序(sort/sorted)

    大家都知道,python排序有内置的排序函数 sort() 和 高阶函数sorted() .但是它们有什么区别呢? 让我们先从这个函数的定义说起: sorted():该函数第一个参数iterable为 ...

  8. linux下ifconfig只剩下lo的解决方法

    运行以下命令,删除旧的网络配置,重新让networkmanager自动配置即可 sudo service network-manager stop sudo rm /var/lib/NetworkMa ...

  9. 第十篇.6、python并发编程之IO模型

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

  10. golang time json mongodb 时间处理

    golang 中解决前端time 输出,后端mongodb中时间存储. package mask import ( "fmt" "time" "go. ...