Java并发工具类
1、Java常见的并发工具类
- CountDownLatch
- CyclicBarrier
- Semaphore
- Exchanger
CountDownLatch
用过Thread的join()都知道,join让主线程等待“子线程”,结束之后,才能继续运行,Jdk1.5之后提供了CountDownLatch。它提供了比Join更丰富的功能,一种共享锁;
常见api
- 构造函数接收一个int值作为计数器,想n个线程等n个点就传如N
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
- countDown();释放共享锁
public void countDown() {
sync.releaseShared(1);
}
应用示例代码:
public class CountDownLatchTest {
static CountDownLatch countDownLatch = new CountDownLatch(2);
public static void main(String[] args) {
try {
new Thread(()->{
try {
System.out.println("1");
countDownLatch.countDown();
Thread.sleep(3000);
System.out.println("2");
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
countDownLatch.await();
System.out.println("3");
} catch (Exception e) {
e.printStackTrace();
}
}
}
CyclicBarrier
表示意思理解为可循环使用的屏障,作用是让一组线程在到达一个屏障时被阻塞,等到最后一个线程到达屏障点,才会让被拦截的线程继续运行。
- 构造函数,parties指的是屏障拦截的线程数
public CyclicBarrier(int parties) {
this(parties, null);
}
- await()调用该方法时表示线程已到达屏障,随即阻塞
应用示例:
public class CyclicBarrierTest {
static CyclicBarrier c = new CyclicBarrier(2);
public static void main(String[] args) {
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(5);
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("1");
}).start();
try {
c.await();
System.out.println("2");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
高级构造函数 CyclicBarrier(int,Runnable)优先执行
public class CyclicBarrierTest2 {
static CyclicBarrier c =new CyclicBarrier(2,new A());
public static void main(String[] args) {
new Thread(
()->{
try {
TimeUnit.SECONDS.sleep(5);
c.await();
System.out.println("1");
} catch (Exception e) {
e.printStackTrace();
}
}
).start();
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("2");
}
private static class A implements Runnable{
@Override
public void run() {
System.out.println("3");
}
}
}
3、两者的区别
- CountDownLatch只能用一次,CyclicBarrier可以reset(),且适合处理复杂逻辑的业务;
- CyclicBarrier还有getNumberWaiting获取当前阻塞的线程数量,isBroken()了解阻塞线程是否中断;
public class CyclicBarrierTest3 {
static CyclicBarrier c =new CyclicBarrier(2);
public static void main(String[] args) {
Thread t = new Thread(()->{
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
});
t.start();
// t.interrupt();
try {
TimeUnit.SECONDS.sleep(2);
System.out.println(c.getNumberWaiting());
c.await();
// System.out.println(c.getNumberWaiting());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Semaphore
- 用来控制同时访问资源的线程数量,通过协调保证合理的使用公共资源;
- 其他常见api
int availablePermits() 返回此信号量中当前可用的许可证数
int getQueueLength() 正在等待获取许可证的线程数
boolean hasQueuedThreads() 是否有线程正在等待获取许可证
void reducePermits() 减少许可证
Collection getQueuedThreads() 返回所有等待获取许可证的线程集
应用示例:
public class SemaphoreTest {
private static final int THREAD_COUNT = 30;
private static ExecutorService pool = Executors.newFixedThreadPool(THREAD_COUNT);
private static Semaphore s = new Semaphore(10);
public static void main(String[] args) {
for (int i = 0; i <THREAD_COUNT ; i++) {
pool.execute(()->{
try {
s.acquire();
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName()+"线程释放资源");
s.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
pool.shutdown();
}
}
Exchanger
线程之间的数据交换,提供一个同步点,两个线程可以交换彼此数据,通过exchange()交换数据,当两个线程执行到exchange()方法,可以将本线程的数据传递给对方。
应用场景:
1、遗传算法
2、校对工作
示例代码:
public class ExchangerTest {
static Exchanger<String> exchanger = new Exchanger();
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
service.execute(()->{
String A ="F";
try {
System.out.println("交换后结果:"+exchanger.exchange(A)); ;
} catch (InterruptedException e) {
e.printStackTrace();
}
});
service.execute(()->{
try {
String B ="B";
String A = exchanger.exchange("C");
System.out.println("是否一致"+A.equals(B)+"A::"+A+"B::"+B);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
service.shutdown();
}
}