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) {
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
SpringMVC 使用JSR-303进行校验 @Valid示例
本篇文章主要介绍了SpringMVC 使用JSR-303进行校验 @Valid示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2017-02-02
spring的TransactionSynchronizationAdapter事务源码解析
这篇文章主要介绍了spring的TransactionSynchronizationAdapter事务源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-09-09


最新评论