Java并发编程线程间通讯实现过程详解
更新时间:2020年05月13日 15:31:40 作者:玄同太子
这篇文章主要介绍了Java并发编程线程间通讯实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
在Java中线程间通讯有多种方式,我这里列出一些常用方式,并用代码的方式展示他们是如何实现的:
- 共享变量
- wait, notify,notifyAll(这3个方法是Object对象中的方法,且必须与synchronized关键字结合使用)
- CyclicBarrier、CountDownLatch
- 利用LockSupport
- Lock/Condition机制
- 管道,创建管道输出流PipedOutputStream和管道输入流PipedInputStream
示例一:
package com.zhi.test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; /** * Java多线程-线程通讯示例<br> * flag作为共享变量JobB执行,notify通知Job执行,CountDownLatch通知主线程执行 * * @author 张远志 * @since 2020年5月4日21:51:24 * */ public class ThreadTest2 { private CountDownLatch latch; private volatile boolean flag = true; private Object lock = new Object(); private AtomicInteger num = new AtomicInteger(0); class JobA implements Runnable { @Override public void run() { synchronized (lock) { flag = false; if (num.get() != 3) { try { lock.wait(); // wait方法会释放锁 } catch (InterruptedException e) { } } System.out.println("任务A收到通知,继续执行作业"); } latch.countDown(); } } class JobB implements Runnable { @Override public void run() { while (flag) { // 保证JobA先申请到锁 } synchronized (lock) { for (int i = 1; i <= 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { } int a = num.incrementAndGet(); System.out.println("任务B第" + i + "次执行,num值为:" + a); if (a == 3) { lock.notify(); // 唤醒JobB线程,notify方法不会释放锁 } } } latch.countDown(); } } @Test public void test() { latch = new CountDownLatch(2); new Thread(new JobA()).start(); new Thread(new JobB()).start(); try { latch.await(); // 保证2个线程都执行完毕 } catch (InterruptedException e) { } } }
结果输出:
任务B第1次执行,num值为:1
任务B第2次执行,num值为:2
任务B第3次执行,num值为:3
任务B第4次执行,num值为:4
任务B第5次执行,num值为:5
任务A收到通知,继续执行作业
示例二:
package com.zhi.test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.LockSupport; import org.junit.Test; /** * Java多线程-线程通讯示例,利用LockSupport * * @author 张远志 * @since 2020年5月4日21:51:24 * */ public class ThreadTest3 { private CountDownLatch latch; private volatile int num = 0; private Thread ta; private Thread tb; class JobA implements Runnable { @Override public void run() { if (num != 3) { LockSupport.park(); } System.out.println("任务A收到通知,继续执行作业"); latch.countDown(); } } class JobB implements Runnable { @Override public void run() { for (int i = 1; i <= 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { } num++; System.out.println("任务B第" + i + "次执行,num值为:" + num); if (num == 3) { LockSupport.unpark(ta); // unpark会立即激活传入线程 } } latch.countDown(); } } @Test public void test() { latch = new CountDownLatch(2); ta = new Thread(new JobA()); tb = new Thread(new JobB()); ta.start(); tb.start(); try { latch.await(); // 保证2个线程都执行完毕 } catch (InterruptedException e) { } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Spring Cloud 专题之Sleuth 服务跟踪实现方法
这篇文章主要介绍了Spring Cloud 专题之Sleuth 服务跟踪,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2021-08-08java8 stream 由一个list转化成另一个list案例
这篇文章主要介绍了java8 stream 由一个list转化成另一个list案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-08-08
最新评论