CyclicBarrier,CountDownLatch和Semaphore
CyclicBarrier
CyclicBarrier是制造一个屏障,多个线程共享一个Barrier对象,到达栅栏处的时候(线程运行达到一个状态),使用cyclicBarrier.await()标记,这时候这个线程停下等待其他线程到达栅栏,所有线程都到达之后,CyclicBarrier失效,运行最初设置的那个线程,如下:
CyclicBarrier cyclicBarrier = new CyclicBarrier(count, () -> {
System.out.println("所有线程到达栅栏处,可以做一些处理");
});
接着所有线程从await()的地方开始运行。
整个Demo:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
class CyclicBarrierTaskTest implements Runnable {
private CyclicBarrier cyclicBarrier;
private int timeout;
public CyclicBarrierTaskTest(CyclicBarrier cyclicBarrier, int timeout) {
this.cyclicBarrier = cyclicBarrier;
this.timeout = timeout;
}
@Override
public void run() {
TestCyclicBarrier.print("is running...");
try {
TimeUnit.SECONDS.sleep(timeout);
TestCyclicBarrier.print("到达栅栏处,等待其他线程到达");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
TestCyclicBarrier.print("所有线程到达栅栏处,继续执行各自线程任务");
}
}
public class TestCyclicBarrier {
public static void print(String str) {
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
System.out.println(df.format(new Date()) + " - " + Thread.currentThread().getName() + ": " +str);
}
public static void main(String[] args) {
int count = 5;
ExecutorService es = Executors.newFixedThreadPool(count);
CyclicBarrier cyclicBarrier = new CyclicBarrier(count, () -> {
System.out.println("所有线程到达栅栏处,可以做一些处理");
});
for (int i = 0; i < count; i++) {
es.execute(new CyclicBarrierTaskTest(cyclicBarrier, (i+1)));
}
}
}
CountDownLatch
设定一个值,之后每次一个线程运行完之后可以调用countDown方法,让这个值减一,减到0之后回到await()的主线程
Demo:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class TaskTest implements Runnable {
private CountDownLatch latch;
private int sleepTime;
/**
*
*/
public TaskTest(int sleepTime, CountDownLatch latch) {
this.sleepTime = sleepTime;
this.latch = latch;
}
/**
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try {
CountDownLatchTest.print(" is running。");
TimeUnit.MILLISECONDS.sleep(sleepTime);
CountDownLatchTest.print(" finished。");
//计数器减减
latch.countDown();
System.out.println(latch.getCount());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CountDownLatchTest {
public static void main(String[] args) {
int count = 10;
final CountDownLatch latch = new CountDownLatch(count);
ExecutorService es = Executors.newFixedThreadPool(count);
for (int i = 0; i < count; i++) {
es.execute(new TaskTest((i + 1) * 1000, latch));
}
try {
CountDownLatchTest.print(" waiting...");
//主线程等待其它事件发生
latch.await();
//其它事件已发生,继续执行主线程
CountDownLatchTest.print(" continue。。。");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
es.shutdown();
}
}
public static void print(String str){
SimpleDateFormat dfdate = new SimpleDateFormat("yy.MM.dd:hh:mm:ss:SS");
System.out.println("[" + dfdate.format(new Date()) + "]" + " " + Thread.currentThread().getName() + ": " + str);
}
一运行latch.await()就进行阻塞等待latch.getcount()降到0,之后从await()处重启
Semaphore
Semaphore则是,线程通过semaphore.acquire(),请求一个信号量,如果请求不到就等待(因为别人把信号量请求光了),等别人调用semaphore.release()方法释放信号量,就可以去竞争请求了。
Demo:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreTest {
public static void print(String str) {
SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss");
System.out.println(df.format(new Date())+" - "+Thread.currentThread().getName()+": "+str);
}
public static void main(String[] args) {
int threadCount = 10;
Semaphore semaphore = new Semaphore(5);
ExecutorService es = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i ++) {
es.submit(new ConsumeResourceTask(semaphore, 1000));
}
es.shutdown();
}
}
class ConsumeResourceTask implements Runnable {
private Semaphore semaphore;
private int sleepTime;
public ConsumeResourceTask(Semaphore semaphore, int sleepTime) {
this.semaphore = semaphore;
this.sleepTime = sleepTime;
}
@Override
public void run() {
try {
semaphore.acquire();
SemaphoreTest.print("占用一个资源");
TimeUnit.MILLISECONDS.sleep(sleepTime);
SemaphoreTest.print("资源占用结束,释放资源");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}