Callable
Callable和Runnable类似,不同点有三个:
- Runnable不返回结果,Callable可以
- Runnable抛出被检查的异常,Callable可以。
- Runnable是run方法,Callable是call方法
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;// 泛型的参数为call方法的返回值
}
Thread(Runnable run)只能接收Runnable类型,而不能接收Callable类型,正好FutureTask是Runnable的实现类,并且能够接收Callable,就将Runnable和Callable联系起来了。
// 抛出了异常
public static void main(String[] args) throws ExecutionException, InterruptedException {
// Thread 只能接收Runnable 不能接收Callable
// FutureTask是Runnable的实现类
// new Thread(new Runnable())=>new Thread(new FutureTask<V>())
// FutureTask(Callable<V> callable)
// new Thread(new FutureTask<V>(callable))
MyThread myThread = new MyThread();//实现Callable
FutureTask<Integer> integerFutureTask = new FutureTask<>(myThread);//接收Callable
new Thread(integerFutureTask, "A").start();//接收FutureTask,它实现了Runnable
new Thread(integerFutureTask, "B").start();// 只会输出一次call,因为结果会被缓存,提高效率
Integer integer = (Integer)integerFutureTask.get();//得到Callable的返回值,这个可能会产生阻塞,因为在返回之前可能有耗时操作。
System.out.println(integer);
}
class MyThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("call");
return 1024;
}
}
常用的辅助类
CountDownLatch(j减法计数器)
通常有必须要执行的任务时使用,线程调用countDown()方法,数量减一,计数器归零后向下执行
//计数器
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//倒计数
CountDownLatch countDownLatch = new CountDownLatch(6);
// 有必须要执行的任务的时候再使用
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 没了");
countDownLatch.countDown(); //-1
}, String.valueOf(i)).start();
}
//六个线程结束了,才往下执行
countDownLatch.await();//等待计数器归零,然后向下执行
System.out.println("结束");
}
}
CyclicBarrier(加法计数器)
// 加法计数器
public class CyclicBarrierDemo {
public static void main(String[] args){
// 参数为 数量,和Runnable
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("成功");
});
for (int i = 0; i < 7; i++) {
final int temp = i;
// 下边lambda 不能直接操作i,因为它本质是new了一个类
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 收集"+(temp+1) +"个");
try {
cyclicBarrier.await();//等待数量达到7,后执行下边的线程
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
Semaphore(信号量)
多个共享资源互斥的使用,并发限流,控制最大线程数。
public class SemaphoreDemo {
public static void main(String[] args) {
// 线程数量,资源较少,线程较多,限流
Semaphore semaphore = new Semaphore(3);//
for (int i = 0; i < 6; i++) {
new Thread(() -> {
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();// 释放许可证
}
}).start();
}
}
}