线程间的通信方式三种 线程间通信
线程间通信(线程间有三种通信方式)
前言在开发中,不可避免的会遇到需要所有子线程在执行后通知主线程处理一些逻辑的场景 。
或者线程A正在执行到某个条件,通知线程B执行某个操作 。
这可以通过以下方式实现:
等待通知机制等待模式是Java中一种经典的线程通信模式 。
两个线程通过对同一对象调用wait()和notify()方法进行通信 。
例如,两个线程交替打印奇偶校验:
public class TwoThreadWaitNotify {private int start = 1;private boolean flag = false;public static void main(String[] args) {TwoThreadWaitNotify twoThread = new TwoThreadWaitNotify();Thread t1 = new Thread(new OuNum(twoThread));t1.setName("A");Thread t2 = new Thread(new JiNum(twoThread));t2.setName("B");t1.start();t2.start();}/*** 偶数线程*/public static class OuNum implements Runnable {private TwoThreadWaitNotify number;public OuNum(TwoThreadWaitNotify number) {this.number = number;}@Overridepublic void run() {while (number.start 输出结果:
t2+-+奇数93t1+-+偶数94t2+-+奇数95t1+-+偶数96t2+-+奇数97t1+-+偶数98t2+-+奇数99t1+-+偶数100这里线程A和线程B都获取了同一个对象的锁,TwoThreadWaitNotify.class线程A调用同步对象的wait()方法释放锁,进入等待状态 。
线程B调用notify()方法,这样线程A就可以在收到通知后从wait()方法返回 。
这里,通过使用TwoThreadWaitNotify.class对象来完成通信 。
有一些事情需要注意:
wait()、notify()和notifyAll()的调用以获得对象(也称为对象监视器)的锁为前提 。
调用wait()方法后,线程将释放锁并进入等待状态,线程将被移动到等待队列中 。
调用notify()方法会将等待队列中的线程移动到同步队列中,并且线程状态会更新为BLOCKED 。
从wait()方法返回的前提是调用notify()方法的线程释放锁,wait()方法的线程获得锁 。
有一个经典的等待范例:
作为消费者的线程:
获取对象的锁 。
输入while(判断条件),调用wait()方法 。
当条件满足时,跳出循环,执行具体的处理逻辑 。
b线程作为生产者:
获取对象锁 。
改变与线程a共享的判断条件 。
调用notify()方法 。
伪代码如下:
//Thread Asynchronized(Object){while(条件){Object.wait();}//do something}//Thread Bsynchronized(Object){条件=false;//改变条件Object.notify();}join() 方法private static void join() throws InterruptedException {Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {LOGGER.info("running");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}) ;Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {LOGGER.info("running2");try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}}}) ;t1.start();t2.start();//等待线程1终止t1.join();//等待线程2终止t2.join();LOGGER.info("main over");}输出结果:
2018-03-16 20:21:30.967 [Thread-1] INFOc.c.actual.ThreadCommunication - running22018-03-16 20:21:30.967 [Thread-0] INFOc.c.actual.ThreadCommunication - running2018-03-16 20:21:34.972 [main] INFOc.c.actual.ThreadCommunication - main over在t1.join()中,它将被阻塞,直到t1的执行完成,因此主线程将等待t1和t2线程的执行 。
实际上,从源代码中可以看出,join()也是一种等待通知机制:
核心逻辑:
while (isAlive()) {wait(0);}在join线程完成后会调用notifyAll()方法,这个方法是在JVM实现中调用的,所以这里看不到 。
volatile 共享内存因为Java使用共享内存进行线程通信,所以主线程可以通过以下方式关闭线程A:
public class Volatile implements Runnable{private static volatile boolean flag = true ;@Overridepublic void run() {while (flag){System.out.println(Thread.currentThread().getName() + "正在运行 。。。");}System.out.println(Thread.currentThread().getName() +"执行完毕");}public static void main(String[] args) throws InterruptedException {Volatile aVolatile = new Volatile();new Thread(aVolatile,"thread A").start();System.out.println("main 线程正在运行") ;TimeUnit.MILLISECONDS.sleep(100) ;aVolatile.stopThread();}private void stopThread(){flag = false ;}}输出结果:
thread A正在运行 。。。thread A正在运行 。。。thread A正在运行 。。。thread A正在运行 。。。thread A执行完毕这里的标志存储在主内存中,所以主线程和线程A都能看到它 。
标志主要是为了内存可见性而装饰的 。更多信息,请点击这里 。
CountDownLatch 并发工具【线程间的通信方式三种 线程间通信】CountDownLatch可以实现和join一样的功能,但是更加灵活 。
private static void countDownLatch() throws Exception{int thread = 3 ;long start = System.currentTimeMillis();final CountDownLatch countDown = new CountDownLatch(thread);for (int i= 0 ;i
推荐阅读
- sp3485中文资料?STM32采用RS485通信,用串口1直接接SP3485可以吗?
- 进程间的通信方式三种 进程间通信
- qq空间爱情说说 爱情空间
- 多田薰和西川茂之间的故事~~《恶作剧之吻》湘琴原型38岁去世,他们的爱情,是你想象的样子吗
- 交通信用卡怎么申请好 交行信用卡办理
- 间笔顺笔画。间的笔画是什么
- 曲高和寡阳春白雪区别 曲高和寡
- 同一本期刊在知网和万方中的目录是不一样的?比如《数字通信世界》这本国家级期刊 数字通信世界是核心期刊吗
- 通信工程概预算教程 通信工程概预算
- 适合情侣之间的睡前故事 爱情小说故事