CountDownLatch
用于一个线程等待多个线程,该类内部维护了一个计数器,当线程调用countdown()方法时计数器减1,当计数器为0时,调用await()方法等待的线程将会被唤醒。
代码如下
public class Test {
public static void main(String[] args) throws InterruptedException {
CountDownLatch cdl=new CountDownLatch(10);
ExecutorService executorService=Executors.newCachedThreadPool(new ThreadFactory() {
AtomicInteger atomicInteger=new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
Thread t=new Thread(r);
t.setName(atomicInteger.getAndIncrement()+"");
return t;
}
});
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
cdl.countDown();
}
});
}
cdl.await();
System.out.println("程序结束");
executorService.shutdown();
}
}
CyclicBarrier
用于多个线程相互等待,当所有线程都到达后,线程才会继续执行。
该类内部维护了一个计数器,当有线程执行await()方法后计数器减1,然后线程等待,等到计数器减为0后,等待的线程才会继续执行。
public class Test {
public static void main(String[] args) {
CyclicBarrier cb=new CyclicBarrier(10);
ExecutorService executorService=Executors.newCachedThreadPool(new ThreadFactory() {
AtomicInteger atomicInteger=new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
Thread t=new Thread(r);
t.setName(atomicInteger.getAndIncrement()+"");
return t;
}
});
for (int i = 0; i <10; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName());
try {
cb.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
});
}
executorService.shutdown();
}
}
semaphore
限制对共享资源的访问线程数,当线程调用acquire()方法时相当于获得了访问权限,调用release()方法释放权限。
代码如下
public class Test {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(3);
ExecutorService executorService=Executors.newCachedThreadPool(new ThreadFactory() {
AtomicInteger atomicInteger=new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
Thread t=new Thread(r);
t.setName(atomicInteger.getAndIncrement()+"");
return t;
}
});
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
System.out.println(semaphore.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
}
});
executorService.shutdown();
}
}
}
FutureTask
FutureTask 可用于异步获取执行结果。当一个计算任务需要执行很长时间,那么就可以用 FutureTask 来封装这个任务,主线程在完成自己的任务之后再去获取结果。通常搭配Callable使用
代码如下
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask futureTask = new FutureTask(new Callable() {
int i = 0;
@Override
public Object call() throws Exception {
for (int j = 0; j < 100; j++) {
i++;
}
return i;
}
});
new Thread(futureTask).start();
int value = (int) futureTask.get();
System.out.println(value);
}
}
BlockingQueue
java.util.concurrent.BlockingQueue 接口有以下阻塞队列的实现:
FIFO 队列 :LinkedBlockingQueue、ArrayBlockingQueue(固定长度)
优先级队列 :PriorityBlockingQueue
提供了阻塞的 take() 和 put() 方法:如果队列为空 take() 将阻塞,直到队列中有内容;如果队列为满 put() 将阻塞,直到队列有空闲位置。
代码实现
class Product {
BlockingQueue bq;
public Product(BlockingQueue bq) {
this.bq = bq;
}
void product() {
try {
bq.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产了一个商品");
}
}
class Consume {
BlockingQueue bq;
public Consume(BlockingQueue bq) {
this.bq = bq;
}
void consume() {
try {
bq.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费了一个商品");
}
}
public class Test {
public static void main(String[] args) {
BlockingQueue bq = new ArrayBlockingQueue(5);
Product product = new Product(bq);
Consume consume = new Consume(bq);
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
@Override
public void run() {
product.product();
}
}).start();
}
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
consume.consume();
}
}).start();
}
}
}
ForkJoin
主要用于并行计算中,把大的计算任务拆分成多个小任务并行计算。
特点:
ForkJoin利用ForkJoinPool实现,ForkJoinPool的线程数量取决于cpu核心数,其中每个线程内部维护了一个双端队列,当其中一个线程完成任务时会从其他线程维护的队列中拿出最后进去的任务来执行,从此提高cpu利用率。
代码如下
class Temp extends RecursiveTask {
private final int critical = 4;
private int first;
private int end;
public Temp(int first, int end) {
this.first = first;
this.end = end;
}
@Override
protected Object compute() {
int result = 0;
if (end - first <= 5) {
for (int i = first; i <= end; i++) {
result += i;
}
} else {
int mid = (end - first) / 2 + first;
Temp left = new Temp(first, mid);
Temp right = new Temp(mid + 1, end);
left.fork();
right.fork();
result = (Integer) left.join() + (Integer) right.join();
}
return result;
}
}
public class Test {
public static void main(String[] args) {
Temp temp = new Temp(1, 10000);
ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.submit(temp);
try {
System.out.println(temp.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
CopyOnWriteArrayList
应用场景当对数组的读操作次数远远大于其他操作(add,set等)时。不会抛出ConcurrentModificationException。
class Read implements Runnable{
static CopyOnWriteArrayList arrayList=new CopyOnWriteArrayList();
static {
arrayList.add(123);
arrayList.add(456);
arrayList.add(789);
}
@Override
public void run() {
Iterator iterator=arrayList.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
arrayList.add("aaa");
}
}
}
public class Test {
public static void main(String[] args) {
Read read=new Read();
for (int i = 0; i < 10; i++) {
new Thread(read).start();
}
}
}