Java并发编程线程间通讯实现过程详解

网友投稿 203 2022-12-07


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多线程-线程通讯示例

* 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 + "次执行,numhttp://值为:" + 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) {

}

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:基于javassist进行动态编程过程解析
下一篇:Java使用BIO和NIO进行文件操作对比代码示例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~