持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天
7.Callable(简单)
- 可以有返回值
- 可以抛出异常
- 方法不同,run()/call()
代码测试
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
new Thread().start();
MyThread thread = new MyThread();
FutureTask futureTask = new FutureTask(thread);//适配器
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start(); //结果会被缓存
Integer o = (Integer) futureTask.get();//获取callable的返回结果
System.out.println(o);
}
}
class MyThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("call()");
return 1024;
}
}
细节:
- 有缓存
- 结果可能需要等待,会阻塞
8.常用的辅助类(必须学会)
8.1 CountDownLatch
//计数器
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"Go out");
countDownLatch.countDown(); // 数量-1
},String.valueOf(i)).start();
}
countDownLatch.await();//等待计数器归零
System.out.println("Close Door");
}
}
原理:
countDownLatch.countDown(); // 数量-1
countDownLatch.await();//等待计数器归零
每次有线程调用countDown()数量-1 , 假设计数器变为0 , countDownLatch就会被唤醒,继续执行。
其实就是一个减法计数器,对于计数器归零之后再进行后面的操作,这是一个计数器!
8.2 CyclicBarrier
其实就是一个加法计数器;
public class CyclickBarrierDemo {
public static void main(String[] args) {
//集齐7颗龙珠召唤神龙
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("召唤神龙成功");
});
//召唤龙珠的过程
for (int i = 1; i <= 7; i++) {
final int temp = i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"收集了"+ temp + "个龙珠");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
8.3 Semaphore
Semaphore:信号量
抢车位:
3个车位 6辆车:
public class SemaphoreDemo {
public static void main(String[] args) {
//线程数量,停车位
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
//acquire 得到
//release 释放
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+ "抢到车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
原理:
semaphore.acquire()获得资源,如果资源已经使用完了,就等待资源释放后再进行使用!
semaphore.release()释放,会将当前的信号量释放+1,然后唤醒等待的线程!
作用: 多个共享资源互斥的使用! 并发限流,控制最大的线程数!