14.走进Callable
- 可以有返回值
- 可以抛出异常
- 方法不同,call()
Runnable的Api文档
FutureTask的Api文档
public class CallableTest {
public static void main(String[] args) {
MyThread thread = new MyThread();
//Callable --- Runnable 中间转换(适配类)
FutureTask<String> futureTask = new FutureTask<>(thread);
//结果会被缓存,提高效率
new Thread(futureTask, "A").start();
new Thread(futureTask, "B").start();
//获取返回值
try {
//这个get方法可能会产生阻塞,把它放到最后
String s = futureTask.get();
//或者使用异步通信来处理
System.out.println(s);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyThread implements Callable<String> {
@Override
public String call() {
System.out.println("call()");
//可能是耗时的操作
return "123";
}
}
输出
call()
123
细节;
- 有缓存
- 结果可能需要等待,会阻塞!
15.CountDownLatch
减法计数器
public class CountDownLatchDemo {
public static void main(String[] args) {
//总数是6 必须要执行的任务的时候再使用
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+" go out");
// 数量-1
countDownLatch.countDown();
}).start();
}
try {
//等待计数器归零,然后再往下执行
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("close door");
}
}
原理:
countDownLatch.countDown(); //数量-1
countDownLatch.await();//等待计数器归零,然后再往下执行
每次线程调用countDown()数量-1,假设计数器变成0,countDownLatch.await()就会被唤醒,继续执行!
16.CyclicBarrier
加法计算器
public class CyclicBarrierDemo {
public static void main(String[] args) {
/**
* 集齐七颗龙珠,召唤神龙
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{
System.out.println("召唤神龙成功!");
});
for (int i = 1; i <= 7; i++) {
final int temp = i;
new Thread(() -> {
System.out.println("收集"+temp+"星龙珠");
try {
//阻塞
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
输出
收集1星龙珠
收集2星龙珠
收集3星龙珠
收集5星龙珠
收集4星龙珠
收集6星龙珠
收集7星龙珠
召唤神龙成功!
17.Semaphore
Semaphore:信号量
抢车位
5辆车,3个停车位
public class SemaphoreDemo {
public static void main(String[] args) {
//3个停车位 限流
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
try {
//获得
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "获得停车位");
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放
semaphore.release();
System.out.println(Thread.currentThread().getName() + "离开停车位");
}
}, String.valueOf(i)).start();
}
}
}
输出
2获得停车位
3获得停车位
1获得停车位
3离开停车位
4获得停车位
2离开停车位
1离开停车位
5获得停车位
4离开停车位
5离开停车位
原理:
semaphore.acquire(); //获得,假设已经满了,等待,等待被释放为止!
semaphore.release();//释放,会将当前的信号量释放,然后唤醒等待线程!
作用:
多个共享资源互斥使用!并发限流,控制最大线程数!