java 并发工具_几个常用并发工具类

这篇文章我们来介绍几个并发编程常用的工具类,它们分别是:CountDownLatch(闭锁,我觉得叫门闩更好理解)

CyclicBarrier(栅栏)

Semophore(信号量)

Exchanger(交换器)闭锁

适用场景:在多线程执行过程中设置几个门闩,当所有的门闩被打开时,被挡在门外的线程才能继续执行。

例子代码:

import java.util.concurrent.*;

public class Demo {

public static void main(String[] args) throws Exception{

System.out.println(Util.testTime(3, new Runnable() {

@Override

public void run() {

System.out.println("test");

}

}));

}

}

class Util{

/*** 测试n个线程并发执行某个任务的时间* @param nThreads 线程数量* @param task 需要并发执行的任务* @return* @throws InterruptedException*/

public static long testTime(int nThreads,final Runnable task) throws InterruptedException {

//为启动门设置一个门闩,当门闩被打开时,放行所有被挡在门外的线程 final CountDownLatch startGate=new CountDownLatch(1);

//为结束门设置n个门闩,当n个门闩被打开时,放行所有被挡在门外的线程 final CountDownLatch endGate=new CountDownLatch(nThreads);

//测试n个线程并发执行任务task的时间 for(int i=0;i

Thread t=new Thread(){

public void run(){

try {

startGate.await();

task.run();

endGate.countDown();

} catch (InterruptedException e) {

endGate.countDown();

}

}

};

t.start();

}

//循环中的内容使得有n个线程在startGate门外等着执行task任务 long start=System.nanoTime();

startGate.countDown();//打开startGate上的门闩 endGate.await();//等待endGate门开 long end =System.nanoTime();

return end-start;

}

}

2. 栅栏

使用场景:多个线程彼此等待,当所有的线程都到达指定“地点”(指定代码位置),才开始继续执行。

例子代码:

public class Demo{

public static void main(String [] args) throws InterruptedException {

final CyclicBarrier cyclicBarrier=new CyclicBarrier(10, new Runnable() {

@Override

public void run() {

System.out.println("10个人都到达会议室,开始开会");

}

});

for(int i=0;i<10;i++){

final long tmp=i;

Thread thread=new Thread(new Runnable() {

@Override

public void run() {

try {

Thread.sleep(1000*(11-tmp));

System.out.println("person"+tmp+" come here");

try {

cyclicBarrier.await();//等待其他线程到达

} catch (BrokenBarrierException e) {

e.printStackTrace();

}

} catch (InterruptedException e) {}

}

});

thread.start();

}

}

}

CountDownLatch和CyclicBarrier这两个类常常容易混淆。但实际上不难区分:CountDownLatch是用来为多个线程设置障碍,在障碍没被消除前,所有的线程必须等候,是“攻坚克难”(障碍解决后才能开会);而CyclicBarrier是对所有的线程进行统筹协调,是“缺一不可”(大家都在才能开会)。

3. 信号量

使用场景:需要控制访问某个资源或者进行某种操作的线程数量。当达到指定数量时,只能等待其他线程释放信号量。

例子代码:

public class Demo{

private static Semaphore semaphore=new Semaphore(2);

public static void main(String [] args) throws InterruptedException {

ExecutorService executorService=Executors.newFixedThreadPool(4);

for(int i=0;i<4;i++) {

executorService.submit(new Runnable() {

@Override

public void run() {

try {

Demo.doSomething();

}catch (InterruptedException e){

System.out.println(Thread.currentThread().getName()+" can't get semaphore.");

}

}

});

}

executorService.shutdown();

while(true){

if(executorService.isTerminated()){

System.out.println("over");

break;

}

}

}

public static void doSomething() throws InterruptedException{

/**

* 每个操作最多两个线程同时进行

*/

System.out.println(Thread.currentThread().getName()+" try to get semaphore.");

semaphore.acquire();

System.out.println(Thread.currentThread().getName()+" is doing something.");

TimeUnit.SECONDS.sleep(5);

System.out.println(Thread.currentThread().getName()+" release semaphore.");

semaphore.release();

}

}

在上面的例子中,同一时刻只有两个线程在操作某种资源和进行某个动作(doSomething)。

4. 交换器

使用场景:用于两个线程之间交换数据

例子代码:

public class Demo{

public static void main(String [] args){

Exchanger exchanger=new Exchanger();

String content1="content1";

String content2="content2";

ExecutorService es=Executors.newFixedThreadPool(2);

es.submit(new ExchangeDataTask(exchanger,content1));

es.submit(new ExchangeDataTask(exchanger,content2));

es.shutdown();

}

}

class ExchangeDataTask implements Runnable{

private Exchanger exchanger;

private V data;

public ExchangeDataTask(Exchanger exchanger,V data){

this.exchanger=exchanger;

this.data=data;

}

@Override

public void run() {

try {

System.out.println(Thread.currentThread().getName()+"交换之前的数据:" + data);

V newData = exchanger.exchange(data);

System.out.println(Thread.currentThread().getName()+"交换之后的数据:" + newData);

}catch (InterruptedException e){

e.printStackTrace();

}

}

}

本文介绍了Java并发编程中常用的几个工具类,希望大家仔细理解。能在合适的场景中使用起来。

介绍Java面试知识点,关注下面 @E-臻 的专栏:Java求职,你要知道的事​zhuanlan.zhihu.com8c0a4a8f404fc83ff70e5d3dd7ad3e78.png

介绍Java学习路线,关注下面 @E-臻 的Live:学习Java,我建议这样做​www.zhihu.com89918ca69e400a01abaa052f42312a11.png

相当程序员,在大学怎么做?关注 @E-臻的Live想当程序员,我建议大学生这样做​www.zhihu.com89918ca69e400a01abaa052f42312a11.png

想学云计算,我该怎么做?关注 @E-臻的Live入门云计算:你该了解的那些事儿​www.zhihu.com89918ca69e400a01abaa052f42312a11.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值