1.CountDownLatch
1.1 概述
1.1.1 简述
CountDownLatch的构造函数入参有N(int类型)个作为计数器;
然后起多子线程,子线程countDownLatch.countDown后计数-1;
主线程countDownLatch.await();
待计数为0后主线程countDownLatch.await()后面继续执行.
CountDownLatch latch = new CountDownLatch(lineCount); //公用对象
latch.countDown(); //子线程
latch.await(); //主线程
1.1.2 特性
-
共享锁(计数只要不为0,所有线程都可以进),
-
CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N;每一次调用CountDownLatch的CountDown的时候的计数器减为0的时候,CountDownLatch的await会阻塞当前线程,直到N变成零.
-
由于countDown方法可以用在任何地方,所以这里说的N个点,可以是N个线程,也可以是1个线程里的N个执行步骤。用在多个线程时,你只需要把这个CountDownLatch的引用传递到线程里。
-
其他方法 如果有某个解析sheet的线程处理的比较慢,我们不可能让主线程一直等待,所以我们可以使用另外一个带指定时间的await方法,await(long time, TimeUnit unit): 这个方法等待特定时间后,就会不再阻塞当前线程。join也有类似的方法。
-
注意:计数器必须大于等于0,只是等于0时候,计数器就是零,调用await方法时不会阻塞当前线程。CountDownLatch不可能重新初始化或者修改CountDownLatch对象的内部计数器的值。一个线程调用countDown方法 happen-before 另外一个线程调用await方法。
1.2 示例
- MultiCountUseCountDownLatch,FileTools
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* 实现,读一个文件,多行数字,
* 然后多线程处理多行数字,
* 所有线程都全部处理完之后,再最终累加每行计算的结果 得到总结果
* 使用CountDownLatch来处理
*/
public class MultiCountUseCountDownLatch {
private int[] nums;
public MultiCountUseCountDownLatch(int line) {
nums = new int[line];
}
public void calc(String line, int index, CountDownLatch latch) {
String[] nus = line.split(","); // 切分出每个值
int total = 0;
for (String num : nus) {
total += Integer.parseInt(num);
}
nums[index] = total; // 把计算的结果放到数组中指定的位置
System.out.println(Thread.currentThread().getName() + " 执行计算任务... " + line + " 结果为:" + total);
latch.countDown();
}
public void sum() {
System.out.println("汇总线程开始执行... ");
int total = 0;
for (int i = 0; i < nums.length; i++) {
total += nums[i];
}
System.out.println("最终的结果为:" + total);
}
/**
* before latch.await
Thread-2 执行计算任务... 23,45,67,78,89 结果为:302
Thread-3 执行计算任务... 12,12 结果为:24
Thread-1 执行计算任务... 21,12,18,45,11 结果为:107
Thread-0 执行计算任务... 10,20,30,33,12,23 结果为:128
after latch.await
汇总线程开始执行...
最终的结果为:561
*/
public static void main(String[] args) {
String filePath = FileTools.getPath();
List<String> contents = FileTools.readFile(filePath);
int lineCount = contents.size();
CountDownLatch latch = new CountDownLatch(lineCount);//等待几个线程完成后集中处理.
MultiCountUseCountDownLatch multiCountUseCountDownLatch = new MultiCountUseCountDownLatch(lineCount);
for (int i = 0; i < lineCount; i++) {
final int j = i;
new Thread(new Runnable() {
@Override
public void run() {
multiCountUseCountDownLatch.calc(contents.get(j), j, latch);
}
}).start();
}
System.out.println("before latch.await");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("after latch.await");
multiCountUseCountDownLatch.sum();
}
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class FileTools {
//读文件行数,一行一个对象放在List<String>中
public static List<String> readFile(String filePath) {
List<String> contents = new ArrayList<>();
String line = null;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(filePath+ File.separator+"nums.txt"));
while ((line = br.readLine()) != null) {
contents.add(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return contents;
}
//获取当前文件的所在的classpath路径
public static String getPath(){
File directory = new File("");// 设定为当前文件夹
String absolutePath= directory.getAbsolutePath();
System.out.println("directory.getAbsolutePath()->" + absolutePath);
Class c = MultiCountNotUseCountDownLatch.class;
String packagePath = c.getPackage().getName();
System.out.println("third.getPackage()->" + packagePath);
packagePath = packagePath.replace(".",File.separator);
System.out.println("third.getPackage2()->" + packagePath);
File file = new File(c.getResource("/").getPath());
System.out.println("file.toString()->"+file.toString());
String filePath = file.toString() + File.separator + packagePath;
return filePath;
}
}
nums.txt 包含数据如下:
10,20,30,33,12,23
21,12,18,45,11
23,45,67,78,89
12,12
1.3 常用构造方法及方法
- CountDownLatch(int count) 构造方法
- countDown() 单个part线程执行完毕
- await() 等待所有part线程完成
- await(long timeout, TimeUnit unit)
- getCount()
1.4 源码
- CountDownLatch
package java.util.concurrent;
public class CountDownLatch {
//构造方法,入口,输入待处理的线程计数器总个数,多个少线程就传给Sync,最终setState的值为线程个数.
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
//释放statue-1,每countDown一次,计数器数字减1,
public void countDown() {
sync.releaseShared(1);
}
//当CountDownLatch中的线程的个数不为0时,一直等待;也就是countDown多次之后,计数器为0了,就不await()了
//等待处理中..,一直等待,可中断的等待.这个在AQS中调用了tryAcquireShared.最终调用Sync的tryReleaseShared
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//重构方法await
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//查看统计线程个数
public long getCount() {
return sync.getCount();
}
private final Sync sync;
//继承AQS的同步器,内部类,由于是共享锁,所以Acquire和Release都是Shared
private static final class Sync extends AbstractQueuedSynchronizer {
Sync(int count) {
setState(count);
}
//状态为0了则返回1,否则-1
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
//释放1
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
//如果状态为0,则不用释放,所以返回fasle
if (c == 0)
return false;
int nextc = c-1;
//如果getState为1,则减-1,直到减到0,则返回true即(nextc==0)
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
public abstract class AbstractQueuedSynchronizer
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//根据tryAcquireShared的返回,如果<0,则加到等待队列中
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
}
2. CyclicBarrier
- Cyclic /'saɪklɪk/ adj. 环的;循环的;周期的
- Barrier /'bærɪɚ/ 障碍物,屏障;界线
2.1概述
2.1.1 简述
同步屏障:像开会,所有人(线程)到齐(先到的人(线程)等待)之后再执行一个总线程,然后总线程执行完之后还可以继续执行各自线程.
//主线程
CyclicBarrier barrier = new CyclicBarrier(int parties, Runnable barrierAction) ;
//子线程
barrier.await();
2.1.2 特性
-
同步屏障,所有的同步方法都到齐的时候,所有的等待方法就会被唤醒.
-
让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
-
如果有一个线程在await()之前发生异常,则不会执行Barrier线程.
2.2 示例
- CyclicBarrierThread
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierThread {
Random random = new Random();
public static void main(String[] args) {
testCycliBarrierBasic();
}
/**
* Thread-9 到达会议室,等待开会..
Thread-8 到达会议室,等待开会..
Thread-0 到达会议室,等待开会..
Thread-7 到达会议室,等待开会..
Thread-6 到达会议室,等待开会..
Thread-2 到达会议室,等待开会..
Thread-1 到达会议室,等待开会..
Thread-5 到达会议室,等待开会..
Thread-3 到达会议室,等待开会..
Thread-4 到达会议室,等待开会..
好!都到齐了,我们开始开会.....
Thread-4 开始发言了..
Thread-7 开始发言了..
Thread-0 开始发言了..
Thread-8 开始发言了..
Thread-9 开始发言了..
Thread-3 开始发言了..
Thread-5 开始发言了..
Thread-1 开始发言了..
Thread-6 开始发言了..
Thread-2 开始发言了..
*/
//测试同步屏障基本功能
public static void testCycliBarrierBasic(){
CyclicBarrierThread cyclicBarrierThread = new CyclicBarrierThread();
//屏障到期后的执行内容
CyclicBarrier barrier = new CyclicBarrier(10, new Runnable() {
//10个独立的线程都执行完成后的执行该段
@Override
public void run() {
System.out.println("好!都到齐了,我们开始开会.....");
}
});
//10个各自执行的线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
cyclicBarrierThread.barrierBasic(barrier);
}
}).start();
}
}
//各多线程执行
public void barrierBasic(CyclicBarrier barrier) {
try {
Thread.sleep(random.nextInt(4000));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 到达会议室,等待开会..");
//各自统一等待,等待所有线程完成,然后再执行CyclicBarrier中的线程
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 开始发言了..");
}
}
- CyclicBarrierExceptionThread
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExceptionThread {
Random random = new Random();
public static void main(String[] args) {
testCycliBarrierException();
}
/**
* Thread-1 到达会议室,等待开会..
Thread-5 到达会议室,等待开会..
Thread-3 到达会议室,等待开会..
Thread-8 到达会议室,等待开会..
Thread-2 到达会议室,等待开会..
Thread-7 到达会议室,等待开会..
Exception in thread "Thread-7" java.lang.RuntimeException: 线程7异常了哟
at course.threadstu.tb5.CyclicBarrierThread.meetingException(CyclicBarrierThread.java:86)
at course.threadstu.tb5.CyclicBarrierThread$4.run(CyclicBarrierThread.java:114)
at java.lang.Thread.run(Thread.java:745)
Thread-4 到达会议室,等待开会..
Thread-9 到达会议室,等待开会..
Thread-6 到达会议室,等待开会..
Thread-0 到达会议室,等待开会..
当有一个线程异常的时候,就不会执行Barrier线程.
*/
public static void testCycliBarrierException(){
CyclicBarrierExceptionThread cyclicBarrierExceptionThread = new CyclicBarrierExceptionThread();
CyclicBarrier barrier = new CyclicBarrier(10, new Runnable() {
//10个独立的线程都执行完成后的执行该段
@Override
public void run() {
System.out.println("好!都到齐了,我们开始开会.....");
}
});
//10个各自执行的线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
cyclicBarrierExceptionThread.meetingException(barrier);
}
}).start();
}
}
//各多线程执行,其中产生异常
public void meetingException(CyclicBarrier barrier) {
try {
Thread.sleep(random.nextInt(4000));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 到达会议室,等待开会..");
if (Thread.currentThread().getName().equals("Thread-7")) {
throw new RuntimeException("线程7异常了哟");
}
//各自统一等待,等待所有线程完成,然后再执行CyclicBarrier中的线程
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 可以发言了..");
}
}
- CyclicBarrierResetThread
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierResetThread {
Random random = new Random();
public static void main(String[] args) {
testCycliBarrierReset();
}
//测试同步屏障同步功能
public static void testCycliBarrierReset(){
CyclicBarrierResetThread cyclicBarrierThread = new CyclicBarrierResetThread();
CyclicBarrier barrier = new CyclicBarrier(10, new Runnable() {
//10个独立的线程都执行完成后的执行该段
@Override
public void run() {
System.out.println("好!都到齐了,我们开始开会.....");
}
});
//10个各自执行的线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
cyclicBarrierThread.meetingReset(barrier);
}
}).start();
}
// 监控等待线程数
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("等待的线程数 " + barrier.getNumberWaiting());
System.out.println("is broken " + barrier.isBroken());
}
}
}).start();
}
//各多线程执行
public void meetingReset(CyclicBarrier barrier) {
try {
Thread.sleep(random.nextInt(4000));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 到达会议室,等待开会..");
if (Thread.currentThread().getName().equals("Thread-7")) {
// Thread.currentThread().interrupt();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
barrier.reset();
}
//各自统一等待,等
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 可以发言了..");
}
}
2.3 常用构造方法和方法
-
CyclicBarrier(int parties) 待屏障的线程个数
-
public CyclicBarrier(int parties, Runnable barrierAction) 屏障到达后执行
-
await() 屏障等待
-
reset() 会导致已经reset后的任务一直等待(reset会new Generation,导致broken为false,则后来线程的状态也不异常,一直等待),reset要慎用.即使待所有线程到达后再reset,要回造成调用reset的线程一直await();
-
isBroken() 是否中断
-
getNumberWaiting() 获取await等待中的线程数目
2.4 源码
//同步屏障,所有的同步方法都到齐的时候,所有的等待方法就会被唤醒.
//如果一个线程发生interrupted,则已经到达的线程都会被notify(breakBarrier)
package java.util.concurrent;
public class CyclicBarrier {
/** The number of parties */
//计数值
private final int parties;
/* The command to run when tripped */
//都达到的时候执行该事件.
private final Runnable barrierCommand;
private final ReentrantLock lock = new ReentrantLock();
private final Condition trip = lock.newCondition();
private Generation generation = new Generation();
//还可以统计还剩余多少线程待执行
private int count;
//验证中断使用
private static class Generation {
//是否中断
boolean broken = false;
}
//构造方法1
/*
创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,
但它不会在启动 barrier 时执行预定义的操作。
*/
public CyclicBarrier(int parties) {
this(parties, null);
}
//构造方法2
/*
创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,
并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
/**
* Main barrier code, covering the various policies.
*/
//核心代码,保证线程安全
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
//中断标志是否中断了.如果中断则异常,还有如果前面有一个线程中断则后来的线程会再这里抛异常.
if (g.broken)
throw new BrokenBarrierException();
//线程有没有被中断.则通过breakBarrier()[改变generation.brokend=true并唤醒所有已到达等待的线程]
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
//count就是parties的,即partThread的个数
int index = --count;
//如果等待线程为0了.则所有的part线程执行完毕,叫醒构造方法中的线程(如果有的话)
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();//如果
ranAction = true;
//修改generation,标识是否执行完成.的叫醒时会用(所有的都叫醒)
nextGeneration();
return 0;
} finally {
if (!ranAction)//如果command.run()时出现异常
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
//执行过程中,所有线程没有完全完成.
for (;;) {
try {
//timed为false
if (!timed)
trip.await(); //即condition.await
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
//发生中断异常时
//说明没被reset,且没被中断,则此时主动中断
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
//如果被中断了.
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
//等待之后被叫醒执行以下三句.broken在线程间传递,还有如果是某个线程中断了则broken为true则抛异常
if (g.broken)
throw new BrokenBarrierException();
//说明被reset了或者完成(command.run())
if (g != generation)
return index;
//超时
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
//叫醒所有part线程
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();//所有的等待线程叫醒trip为Condition
// set up next generation
count = parties; //然后count设置为初始值个数
generation = new Generation(); //generation也重置,其实就broken为false
}
//打破屏障
private void breakBarrier() {
generation.broken = true; //回归初始值
count = parties; //回归初始值
trip.signalAll(); //叫醒所有线程
}
//还支持reset,重置
/
public void reset() {
final ReentrantLock lock = this.lock;
//加锁
lock.lock();
try {
//此时
breakBarrier(); // break the current generation
//由于一个new 一个 generation,所以broken为false,后来的线程不能抛异常,一直等待
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
}
3. Semaphore
Semaphore: /'sɛməfɔr/ 信号;旗语;臂板信号机
3.1.概述
- Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源 只有指定数目的线程可以执行.当多余该数据的线程时,其它线程等待,当前面有线程结束后,可以继续新的线程执行. 有点类似于线程池(ExecutorService threadPool = Executors.newFixedThreadPools(10))
- Semaphore可以用于做流量控制,特别公用资源有限的应用场景,比如数据库连接
- 多个线程进入,所以是共享锁.
//主线程
Semaphore semaphore = new Semaphore(10);
//子线程
semaphore.acquire();
semaphore.release();
3.2.示例
- SemaphoreThread
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreThread {
public void semaphoreExecute(Semaphore semaphore) {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is run ...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release();
}
public static void main(String[] args) {
SemaphoreThread semaphoreThread = new SemaphoreThread();
Semaphore semaphore = new Semaphore(10);
int i=0;
while(i<100) {
new Thread(new Runnable() {
@Override
public void run() {
semaphoreThread.semaphoreExecute(semaphore);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
i++;
}
//类似于如下功能,这个线程池中只有10个线程而SemaphoreThread只执行10个
executors();
}
public static void executors(){
ExecutorService threadPool = Executors.newFixedThreadPool(10);
int j=0;
while(j<100) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 执行...");
}
}).start();
j++;
}
}
}
3.3.常用构造方法和方法
- Semaphore(int permits) 构造方法,默认非公平
- Semaphore(int permits, boolean fair) 可以构造共平;非公平
- acquire() 获取
- release() 释放
3.4.源码
package java.util.concurrent;
public class Semaphore implements java.io.Serializable {
private final Sync sync;
//内部类
abstract static class Sync extends AbstractQueuedSynchronizer {
Sync(int permits) {
setState(permits);
}
//核心代码,就是判断一下当前是否还有可余量.如果还有则可以获取,如果没有则不能获取.
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
//构造方法1
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
//构造方法2
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
//常用方法1
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//常用方法2
public void release() {
sync.releaseShared(1);
}
//内部类-不公平锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
//内部类-公平锁
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
FairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
for (;;) {
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
}
3.5 参考文章
4. Exchanger
Exchanger: /ɪks'tʃendʒər/ n.交换器;交易所;交换程序
4.1.概述
-
Exchanger 是一个用于线程间协作的工具类,Exchanger用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange 方法交换数据,如果第一个线程先执行exchange 方法,它会一直等待第二个线程也执行exchange 方法,当两个线程都到达同步点时,这两个线程就可以交换数据
-
偶数个线程成对出现,如果出现奇数个,则最后一个线程等待了.
-
如果多个线程,则先到达的连续到达的两个数据交互,并且处理,然后后续再到达的两个再处理.也就是连续成对处理并清空
-
使用场景: 彩票,多线程多网站抓数据. 依赖于多线程的结果数据,然后在比较结果. 没抓到可以设置超时时间.
-
示例:4
//主线程
Exchanger<String> exch = new Exchanger<>();
//子线程
String value =exch.exchange(res);
4.2.示例
ExchangerThread
4.3.源码
package java.util.concurrent;
public class Exchanger<V> {
public V exchange(V x) throws InterruptedException {
Object v;
Object item = (x == null) ? NULL_ITEM : x; // translate null args
if ((arena != null ||
(v = slotExchange(item, false, 0L)) == null) &&
((Thread.interrupted() || // disambiguates null return
(v = arenaExchange(item, false, 0L)) == null)))
throw new InterruptedException();
return (v == NULL_ITEM) ? null : (V)v;
}
}