Callable
- 可以有返回值
- 可以抛出异常
- 方法不同:run/call
怎么让Callable能够启动线程呢?
测试
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
1. @Description
2. @ClassName CallableTest
3. @Author cai feifei
4. @date 2020.10.24 12:36
5. @Version
*/
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread thread = new MyThread();
//适配类
FutureTask<String> futureTask = new FutureTask<>(thread);
new Thread(futureTask,"A").start();
//有缓存,所以控制台只打印了一次call方法
new Thread(futureTask,"B").start();
//get可能会存在阻塞,解决放到最后,或者使用异步通信处理
String s = futureTask.get();
System.out.println(s);
}
}
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("执行了call()方法");
return "1024";
}
}
两个细节:
- 使用callable会有缓存
- get方法可能会发生阻塞
常用的辅助类
CountDownLatch、CyclicBarrier、Semaphore
CountDownLatch(减法计数器)
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
//总数是10,必须执行任务时使用
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i=0;i<10;i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"出队");
//数量减一,每个线程执行完毕
countDownLatch.countDown();
}).start();
}
//必须等待计数器归零了,才能继续往下执行
countDownLatch.await();
System.out.println("队列清空了");
}
}
原理:
countDownLatch.countDown()
数量减一
countDownLatch.await()
计数器归0时,等待结束,向下继续执行
每调用一次countDown(),计数器减1,当减为0时,countDownLatch.await()被唤醒,继续向下执行
CyclicBarrier(加法计数器)
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(10,()->{
System.out.println("集齐10张普通卡片,可兑换高级卡片!");
});
for (int i=1;i<=10;i++){
//lamda不能直接获得i,因为开启一个线程相当于另起一个类;所以需要定义一个final变量,作为中间值
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();
}
}
}
Semaphore(信号量)
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* @Description
* @ClassName SemaphoreTest
* @Author cai feifei
* @date 2020.10.24 14:24
* @Version
*/
public class SemaphoreTest {
public static void main(String[] args) {
//线程数量;停车位;限流
Semaphore semaphore = new Semaphore(3);
//6辆车来停车
for (int i=1;i<=6;i++){
new Thread(()->{
try {
//acquire得到
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"停入车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//release释放
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
semaphore.acquire()
获得资源;如果资源都被占了,等待,等待被释放为止
semaphore.release()
释放资源;将当前信号量释放+1,唤醒等待的线程
作用:多个共享资源互斥的使用,并发限流,控制最大的线程数
上一篇:JUC详解4——集合相关
下一篇:JUC详解6——读写锁