1、CountDownLatch
作用:完成一组在其他线程的操作之前,使得一个或多个线程一直等待。
构造方法: CountDownLatch(int count) count为计数器的总数
其他方法:
countDown(),每调用一次,count减一
await(),在count等于0之前,使得当前线程一直处于等待状 态,直到count等于0,该线程开始执行。
例子:
final CountDownLatch countDownLatch = new CountDownLatch(2);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG,"Thread1 is start");
try {
Thread.sleep(1000);
Log.d(TAG,"Thread1 is finish");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();//建议在finally中执行
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG,"Thread2 is start");
try {
Thread.sleep(1000);
Log.d(TAG,"Thread2 is finish");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
}
}
});
thread1.start();
thread2.start();
try {
countDownLatch.await();
Log.d(TAG,"mainThread is start");
} catch (InterruptedException e) {
e.printStackTrace();
}
结果:
2、cyclicbarrier
作用:可以使一组线程互相等待,直到到达设置的parties值。
构造方法:
CyclicBarrier(int parties, Runnable barrierAction)
parties:线程数量,barrierAction:到达parties后执行的runnable。
其他方法:
await():使当前线程进入等待状态
reset():将CyclicBarrier重置为初始状态
例子:
final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
Log.d(TAG,"Inside Barrier");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
for (int i=0;i<5;i++){
new Thread(new BarrierRunnable(cyclicBarrier)).start();
}
class BarrierRunnable implements Runnable{
CyclicBarrier cyclicBarrier;
public BarrierRunnable(CyclicBarrier cyclicBarrier){
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
Log.d(TAG,Thread.currentThread().getId()+"is waiting");
try {
cyclicBarrier.await();
Log.d(TAG,Thread.currentThread().getId()+"is working");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
结果:
3、Semaphore
作用:Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做完自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。
使用方法:
// 创建一个计数阈值为5的信号量对象
// 只能5个线程同时访问
Semaphore semp = new Semaphore(5);
try {
// 申请许可
semp.acquire();
try {
// 业务逻辑
} catch (Exception e) {
} finally {
// 释放许可
semp.release();
}
} catch (InterruptedException e) {
}
例子:
final Semaphore semaphore = new Semaphore(3);
ExecutorService executorService = Executors.newFixedThreadPool(6);
for (int i=0;i<9;i++){
final int j=i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
Log.d(TAG,"Thread"+j+"获取资源"+System.currentTimeMillis());
Thread.sleep(5000);
semaphore.release();
//Log.d(TAG,"Thread"+j+"释放资源"+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();
结果:
可以看到虽然线程池设置了固定大小为6,但是由于信号量设置为3,同一时间只有三个线程可以得到执行。