文章目录
BlockingQueue
概念
- 阻塞
- 队列间关系
- 使用阻塞队列的场景
多线程并发处理,线程池!
四组API
方式 | 抛出异常 | 有返回值 | 阻塞等待 | 超时等待 |
---|---|---|---|---|
添加 | add | offer | put | offer(,) |
移除 | remove | poll | take | poll(,) |
检测队列首 | element | peek |
- 抛出异常
/**
* 抛出异常
*/
public static void test01(){
//队列的大小,即最多放多少个数据
ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
System.out.println(queue.add("a"));
System.out.println(queue.add("b"));
System.out.println(queue.add("c"));
//java.lang.IllegalStateException: Queue full 抛出异常!
System.out.println(queue.add("d"));
System.out.println("===============");
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
//java.util.NoSuchElementException 抛出异常!
System.out.println(queue.remove());
}
- 不会抛出异常
/**
* 有返回值,没有异常
*/
public static void test02(){
//队列的大小,即最多放多少个数据
ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
System.out.println(queue.offer("a"));
System.out.println(queue.offer("b"));
System.out.println(queue.offer("c"));
//false 不抛出异常!
System.out.println(queue.offer("d"));
System.out.println("===============");
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
//null 不抛出异常!
System.out.println(queue.poll());
}
- 阻塞 等待
/**
* 等待,阻塞(一直阻塞)
*/
public static void test03() throws InterruptedException {
//队列的大小,即最多放多少个数据
ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
//无返回值,一直阻塞
queue.put("a");
queue.put("b");
queue.put("c");
//队列没有位置了,线程会一直等待
queue.put("d");
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
//没有这个元素,线程会一直等待
System.out.println(queue.take());
}
- 超时等待
/**
* 等待,阻塞(超时等待)
*/
public static void test04() throws InterruptedException {
//队列的大小,即最多放多少个数据
ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
queue.offer("a",10L, TimeUnit.SECONDS);
queue.offer("b",10L, TimeUnit.SECONDS);
queue.offer("c",10L, TimeUnit.SECONDS);
//等待超过5秒就退出
queue.offer("d",5L, TimeUnit.SECONDS);
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
//等待超过2秒就退出
System.out.println(queue.poll(2L,TimeUnit.SECONDS));
}
SynchronousQueue同步队列
代码
/**
* 同步队列
* 和其他的BlockingQueue 不一样, synchronousQueue 不存储元素
* 即 put了一个元素,必须从里面先take取出来,否则不能再put进去
*/
BlockingQueue<String> synchronousQueue = new SynchronousQueue<>();
new Thread(()->{
try {
synchronousQueue.put("1");
synchronousQueue.put("2");
synchronousQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(3L);
System.out.println(synchronousQueue.take());
TimeUnit.SECONDS.sleep(3L);
System.out.println(synchronousQueue.take());
TimeUnit.SECONDS.sleep(3L);
System.out.println(synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
线程池
池化技术
- 概念
事先准备好一些资源,有人要用,就来这里拿,用完还
线程池、连接池、内存池、对象池…创建、销毁。十分浪费资源
- 好处
- 降低资源的消耗
- 提高响应的速度
- 方便管理
线程复用,可以控制最大并发数、管理线程
线程池创建
- 阿里巴巴手册
三大方法
// 本质都是threadPoolExecutor
ExecutorService threadPool =
// Executors.newSingleThreadExecutor();// 单个线程
// Executors.newFixedThreadPool(5); // 创建固定的线程池的大小
Executors.newCachedThreadPool(); // 可伸缩的
七大参数
public ThreadPoolExecutor(int corePoolSize, //核心线程数量
int maximumPoolSize, //非核心线程数量
long keepAliveTime, // 非核心线程保持时长,超时了没有人调用就会释放
TimeUnit unit, // 时长单位
BlockingQueue<Runnable> workQueue, // 阻塞队列
ThreadFactory threadFactory, // 线程工厂(创建线程的,一般不用动)
RejectedExecutionHandler handler) // 拒绝策略
业务图原理
四大拒绝策略
- 直接抛出异常(AbortPolicy)
new ThreadPoolExecutor.AbortPolicy()
- 哪来的去哪里(如由main线程执行)(CallerRunsPolicy)
new ThreadPoolExecutor.CallerRunsPolicy()
- 队列满了,丢弃任务,不会抛出异常(DiscardPolicy)
new ThreadPoolExecutor.DiscardPolicy()
- 队列满了,尝试去和最早的竞争,也不会抛出异常(DiscardOldestPolicy)
new ThreadPoolExecutor.DiscardOldestPolicy()
最大线程池设置
- CPU 密集型:几核就是几,可以保持CPU的效率最高
int num = Runtime.getRuntime().availableProcessors();- IO 密集型:判断程序中十分耗IO的程序数量,可为两倍
向线程池提交任务
1. execute
// 没有返回值,直接提交任务( Runnable )
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
pool.execute(new Runnable() {
@Override
public void run() {
}
});
2. submit
// 有返回值,传入的是FutureTask接口实现类
Future<?> submit = pool.submit(new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 1;
}
}));
// 通过get获取返回值,若线程还没执行完会先阻塞
try {
Object o = submit.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}