Callable
Callable类似于Runnable,然而Runnable不会返回结果,也不会抛出执行时的异常。
static class Test1 implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("call()");
return "已调用";
}
}
实现Callable接口需要覆写其实现方法,其方法的返回值对应着参数V
启动Callable
//new Thread(new Runnable()).start();
//new Thread(new FutureTask<V>()).start();
//new Thread(new FutureTask<Callable>()).start();
Test1 test1=new Test1();
FutureTask futureTask=new FutureTask(test1);//适配类
new Thread(futureTask,"A").start();
System.out.println(futureTask.get());//需等待,可能会产生阻塞
通过连接第三方适配类Futuretask启动Callable
结果:
countDownLatch
允许一个或多个线程等待直到其他线程执行完一组操作,用于计数
示例
当运行的线程数小于设定线程数,
CountDownLatch countDownLatch=new CountDownLatch(6);//用于计数
for (int i = 1; i <= 4; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"当前线程执行完毕");
countDownLatch.countDown();//计数器减一
},String.valueOf(i)).start();
}
countDownLatch.await();//计数器归零之后才向下操作
System.out.println("所有线程执行完毕");
注意参数线程数和实际线程数的关系!
结果:
造成线程一直等待,无法达到设定线程数量
当运行的线程数大于设定线程数:
结果:
当运行的线程数等于设定线程数:
多线程无论顺序,所有线程执行完毕,计数器归零,才会继续往下执行。
CyclicBarrier
允许一组线程全部等待彼此达到共同屏障点的同步辅助,循环阻塞在涉及固定大小的线程方式很有用,屏障被称为循环。
例
当线程数大于或者小于设定的参数线程时,造成线程等待
/**
* @author
* @Date 2022/7/18
* @apiNote
*/
CyclicBarrier cyclicBarrier=new CyclicBarrier(6,()->{
System.out.println("所有线程已完成,准备就绪下一个步骤");
});
for (int i = 1; i <= 5; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"当前线程执行完毕");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
执行:
循环次数改为8时:
结果:
只有设定线程数与运行线程数数量一样时:
结果:
Semaphore
一个计数信号量,在概念上,信号量维持一个许可证,如果有必要,每个Acquire()都会阻塞,直到许可证可用然后才能使用它。
例:
/**
* @author
* @Date 2022/7/18
* @apiNote
*/
Semaphore semaphore=new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(()->{
try {
System.out.println("初始许可数为3");
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"当前线程抢到许可,剩余许可"+semaphore.availablePermits());
TimeUnit.SECONDS.sleep(3);
semaphore.release();
System.out.println(Thread.currentThread().getName()+"当前线程释放许可,剩余许可"+semaphore.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
结果:
用于限流,指定线程执行的个数,多个线程互斥作用。
semaphore.acquire()获得。如果已经满了,则等待,直到释放为止。
semaphore.release()释放。会将当前位置释放,唤醒等待线程。