一、Callable接口
- Callable 和 Runable 对比:比如Callable 是你自己,你想通过你的女朋友 Runable 认识她的闺蜜 Thread
- Callable 是 java.util 包下 concurrent 下的接口,有返回值,可以抛出被检查的异常
- Runable 是 java.lang 包下的接口,没有返回值,不可以抛出被检查的异常
- 二者调用的方法不同,run()/ call()
- 代码演示
class MyThread implements Callable<Integer> {
@Override
public Integer call() {
System.out.println("call()"); // A,B两个线程会打印几个call?(1个)
// 耗时的操作
return 1024;
}
}
//class MyThread implements Runnable {
//
// @Override
// public void run() {
// System.out.println("run()"); // 会打印几个run
// }
//}
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// new Thread(new Runnable()).start();// 启动Runnable
// new Thread(new FutureTask<V>()).start();
// new Thread(new FutureTask<V>( Callable )).start();
new Thread().start(); // 怎么启动Callable?
// new 一个MyThread实例
MyThread thread = new MyThread();
// MyThread实例放入FutureTask
FutureTask futureTask = new FutureTask(thread); // 适配类
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start(); // call()方法结果会被缓存,提高效率,因此只打印1个call
// 这个get 方法可能会产生阻塞!把他放到最后
Integer o = (Integer) futureTask.get();
// 或者使用异步通信来处理!
System.out.println(o);// 1024
}
}
二、辅助类-CountDownLatch
- 减法计数器: 实现调用几次线程后,再触发某一个任务。
// 计数器
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
// 总数是6,必须要等执行的任务完成时,再使用!
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.await() 就会被唤醒,继续执行!
三、辅助类-CyclicBarrier
public class CyclicBarrierDemo {
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;
// lambda能操作到 i 吗
new Thread(()->{
System.out.println(Thread.currentThread().getName()
+"收集"+temp+"个龙珠");
try {
cyclicBarrier.await(); // 等待
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
四、辅助类-Semaphore
public class SemaphoreDemo {
public static void main(String[] args) {
// 线程数量:停车位! 限流!、
// 如果已有3个线程执行(3个车位已满),则其他线程需要等待‘车位’释放后,才能执行!
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
// acquire() 得到
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(); // release() 释放
}
},String.valueOf(i)).start();
}
}
}
-
semaphore.acquire():获得,假设如果已经满了,等待,等待被释放为止! -
semaphore.release():释放,会将当前的信号量释放 + 1,然后唤醒等待的线程! -
作用:多个共享资源互斥的使用!并发限流,控制最大的线程数!
|