1.CountDownLatch
await(),进入等待的状态
countDown(),计数器减一
应用场景:启动三个线程计算,需要对结果进行累加。
CountDownLatch使用
package com.ljessie.sinopsis.util;
import java.util.concurrent.CountDownLatch;
/**
* 等待所有线程都执行完毕之后,再执行
* @author zbw
*
*/
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(8);
//模拟裁判,等所有选手都完成比赛的情况下,才会继续进行
new Thread() {
public void run() {
try {
countDownLatch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("800米比赛结束,清空跑道");
}
}.start();
//模拟参赛运动员
for (int i = 0; i < 8; i++) {
int finalI = i;
new Thread() {
public void run() {
try {
Thread.sleep(finalI*1000);
System.out.println("到达终点:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//选手完成比赛
countDownLatch.countDown();
}
}
}.start();
}
}
}
2.CyclicBarrier--栅栏
允许一组线程相互等待达到一个公共的障碍点,之后再继续执行
跟countDownLatch的区别
CountDownLatch一般用于某个线程等待若干个其他线程执行完任务之后,它才执行;不可重复使用 CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;可重用的
package com.ljessie.sinopsis.util;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* 等所有线程都到达某一状态时,再一起执行
* @author zbw
*
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(8);
for (int i = 0; i < 8; i++) {
int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(finalI * 1000);
System.out.println("准备就绪:"+Thread.currentThread().getName());
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("起跑:"+Thread.currentThread().getName());
}
}).start();
}
}
}
3.Semaphore--信号量
控制并发数量
使用场景:接口限流
package com.ljessie.sinopsis.util;
import java.util.concurrent.Semaphore;
/**
* 信号量,控制并发数量。
* @author zbw
*
*/
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(8);
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("开始执行:"+Thread.currentThread().getName());
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//线程执行完毕,释放资源
semaphore.release();
}
}
}).start();
}
}
}
4.Exchanger--用于交换数据
它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是【成对】的。
package com.ljessie.sinopsis.util;
import java.util.concurrent.Exchanger;
/**
* 用来交换数据的,两个线程通过exchange方法交换数据,如果第一个线程先
* 执行exchange方法,它会一直等待第二个线程也执行exchange方法。
* 将本线程生产的数据交换给对方。
* @author zbw
*
*/
public class ExchangerDemo {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<String>();
String str1 = "zbw";
String str2 = "jessie";
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"初始值------>"+str1);
try {
String exchangeString = exchanger.exchange(str1);
System.out.println(Thread.currentThread().getName()+"交换后------>"+exchangeString);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"初始值------>"+str2);
try {
Thread.sleep(2000);
String exchangeString = exchanger.exchange(str2);
System.out.println(Thread.currentThread().getName()+"交换后------>"+exchangeString);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
网友评论