8. Java中的并发工具类
提供并发流程控制
- CyclicBarrier
- CountDownLatch
- Semaphore
线程间交换数据
- Exchanger
1. CountDownLatch
CountDownLatch允许一个或多个线程等待其他线程完成操作,类似于一个计数器。构造参数会传入一个N值,当调用CountDownLatch的countDown方法,N就会-1,await方法会阻塞当前线程,直到N等于0。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest {
static CountDownLatch count = new CountDownLatch(5) ;
public static void main(String[] args) throws InterruptedException {
for (int i = 0 ; i<5 ; i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
count.countDown();
count.countDown();
}
} , "thread"+i) ;
t.start();
}
count.await();
System.out.println("main thread");
}
}
thread1
thread4
thread2
111
thread3
thread0
2. CyclicBarrier
让一组线程达到一个屏障(同步点)阻塞,直到最后一个线程屏障时,所有被屏障拦截的线程才会继续运行。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
static CyclicBarrier c = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("thread c ");
}
}) ;
public static void main(String[] args) {
for (int i=0 ; i<10; i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
try {
c.await() ;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
} , "thread-"+i) ;
t.start();
}
}
}
thread-0
thread-2
thread-3
thread-6
thread-7
thread c
thread-1
thread-4
thread-5
thread-8
thread-9
thread c
可见执行了两遍(一组5个线程)
CyclicBarrier应用场景:多线程计算数据、合并计算结果的场景。
import java.util.Map;
import java.util.concurrent.*;
public class BankWaterService implements Runnable{
private CyclicBarrier c = new CyclicBarrier(4 ,this) ;
private Executor executor = Executors.newFixedThreadPool(4) ;
private ConcurrentHashMap<String , Integer> sheetBankWaterCount = new ConcurrentHashMap<>() ;
private void count(){
for (int i=0 ; i<4 ; i++){
executor.execute(new Runnable() {
@Override
public void run() {
sheetBankWaterCount.put(Thread.currentThread().getName() , 1) ;
try {
c.await() ;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("结束");
}
});
}
}
@Override
public void run() {
int result = 0 ;
for (Map.Entry<String,Integer> entry : sheetBankWaterCount.entrySet()) {
result += entry.getValue() ;
}
sheetBankWaterCount.put("result" , result) ;
System.out.println(result);
}
public static void main(String[] args) {
BankWaterService bankWaterService = new BankWaterService() ;
bankWaterService.count();
}
}
4
结束
结束
结束
结束
3. Semaphore
用来控制同时访问特定资源的线程数量,通过协调各个资源,保证合理的使用公共资源。Semaphore可以用做流量控制,比如数据库连接等等。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
private static final int THREAD_COUNT = 30 ;
private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT) ;
//10为许可证的数量,表示最大并发线程数为10
private static Semaphore s = new Semaphore(10) ;
public static void main(String[] args) {
for (int i=0 ; i<THREAD_COUNT ; i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
//获得许可证
s.acquire();
System.out.println("save data");
//归还许可证
s.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
threadPool.shutdown();
}
}
- intavailablePermits():返回信号量中当前可用的许可证数
- intgetQueueLength():返回正在等待获取许可证的线程数
- booleanhasQueuedThreads():是否有线程正在等待获取许可证
- protented void reducePermits(int reduction):减少reduction个许可证
- protented Collection getQueuedThreads():返回所有等待获取许可证的线程集合
4. Exchanger
Exchanger它提供一个同步点,用于进行线程间的数据交换,如果第一个线程先执行exchange方法,它会等待第二个线程也执行exchange方法,当两个线程到达同步点后,就可以交换数据。如果有一个线程没执行exchange方法,则一直等待下去。
- 遗传算法
- 校对工作
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExchangerTest {
private static final Exchanger<String> exgr = new Exchanger<>() ;
private static ExecutorService service = Executors.newFixedThreadPool(2) ;
public static void main(String[] args) {
service.execute(new Runnable() {
@Override
public void run() {
String a = "银行流水帐a" ;
try {
exgr.exchange(a) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
String b = "银行流水帐b" ;
String a = null ;
try {
a = exgr.exchange("B") ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(a.equals(b));
System.out.println(a);
System.out.println(b);
}
});
service.shutdown();
}
}
false
银行流水帐a
银行流水帐b