1.阻塞队列(blockQueue)
阻塞队列:存储的时候,当容量满了就形成了阻塞;取得时候,当容量空了也行成了阻塞。
有什么用?-----> 多线程程序中线程间通信的异步消息实现。
collection 下面有set、list、queue
queue下面有blockQueue,阻塞队列有ArrayBlockQueue& LinkBlockDueue(双端队列效率高)
阻塞队列应对新加元素的策略:
策略 | 报错策略 | 丢弃策略 | 有超时等待 | 永久等待 |
---|---|---|---|---|
添加 | add | offer(e) | offer(e, timeout) | put |
取出 | remove | poll | poll | take |
检查 | element | peek | 无 | 无 |
描述 | 有多的元素就抛出错误 | 成功返回true失败false,元素丢掉 | 等待到超时时间,时间到了丢弃 | 阻塞等待 |
public static void main(String[] args) throws InterruptedException {
// 生成队列的时候要定义大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
/**
* 第一组 报错
*/
// java.lang.IllegalStateException: Queue full
// blockingQueue.add("a");
// blockingQueue.add("b");
// blockingQueue.add("c");
// 取出
// System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove());
// // 检查
// System.out.println(blockingQueue.element());
/**
* /第二组 不报错 丢弃元素
*/
// 放入
// System.out.println(blockingQueue.offer("a")); //true
// System.out.println(blockingQueue.offer("b"));
// System.out.println(blockingQueue.offer("c"));
// 取出
// blockingQueue.poll();
// blockingQueue.poll();
// blockingQueue.poll();
// 检查
// blockingQueue.peek();
/**
* 第三组 有超时的存入
*/
// 存入 超时时间为3秒
// blockingQueue.offer("a",3L, TimeUnit.SECONDS);
// blockingQueue.offer("b",3L, TimeUnit.SECONDS);
// blockingQueue.offer("c",3L, TimeUnit.SECONDS);
// 取出 超时时间为3秒
// blockingQueue.poll(3L, TimeUnit.SECONDS);
// blockingQueue.poll(3L, TimeUnit.SECONDS);
// blockingQueue.poll(3L, TimeUnit.SECONDS);
/**
* 第四组 阻塞存入
*/
//存入 会一直等待
// blockingQueue.put("a");
// blockingQueue.put("b");
// blockingQueue.put("c");
//
// blockingQueue.put("e"); // 没有存入一直等待
// 取出
// blockingQueue.take();
// blockingQueue.take();
// blockingQueue.take();
}
同步线程SynchronousQueue
一次只有一个元素。一个特殊的阻塞线程。
2.线程池(3+7+4)
为什么会有池?-----提高程序的性能,提高使用率,降低消耗。
3种方法
(注意,阿里开发手册不允许使用这三种方法,容易OOM)
Executors
可以有三种创立线程池的方法。
public static void main(String[] args) {
// Executors 通过这个工具类产生
// 单例的 只有一个线程
ExecutorService executor = Executors.newSingleThreadExecutor();
// 固定的线程数
ExecutorService executor2 = Executors.newFixedThreadPool(8);
// 弹性池 可伸缩(最大不超过2147483647个)
ExecutorService executor3 = Executors.newCachedThreadPool();
// 使用线程池
executor.execute(()->{
System.out.println("里面是个Runnable接口 可以用表达式");
});
// 线程池关闭
executor.shutdown();
}
7大参数
为什么阿里不允许使用呢?----点进去的源码都是用ThreadPoolExecutor
,会使用阻塞队列,最大值是integer.MAX_VALUE
会造成OOM。
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>())
// 对应的构造器
public ThreadPoolExecutor(int corePoolSize, // 常用池子的大小
int maximumPoolSize, // 最大线程池大小
long keepAliveTime,// 差量线程等待时间数值
TimeUnit unit,// 时间单位
BlockingQueue<Runnable> workQueue)//阻塞队列类型
点进去看线程池的源码发现生成线程池的7个参数,
public ThreadPoolExecutor(int corePoolSize, // 核心池线程数大小 (常用)
int maximumPoolSize, // 最大的线程数大小 (常用)
long keepAliveTime, // 超时等待时间 (常用)
TimeUnit unit, // 时间单位 (常用)
BlockingQueue<Runnable> workQueue, // 阻塞队列(常用)
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略(常用))
4种拒绝策略
报错,丢弃异常ThreadPoolExecutor.AbortPolicy();
不报错,丢弃任务ThreadPoolExecutor.DiscardPolicy();
失效前尝试获取资源hreadPoolExecutor.DiscardOldestPolicy();
哪儿来的回哪儿去ThreadPoolExecutor.CallerRunsPolicy();
下面的是相关的源码Runnable 是调用的线程r,ThreadPoolExecutor 线程池e
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
// r为进入的线程 关闭时 执行r的行为-----即哪儿来的回哪儿去
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
// 生成拒绝执行异常RejectedExecutionException
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
// 与上面的差一个报错 即不进行报错
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
// e在关闭之前是试着执行
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
最大线程池 该如何设置--------
CPU密集型: 根据CPU的处理器数量来定!保证最大效率
IO密集型: 50 个线程都是进程操作大io资源, 比较耗时! > 这个常用的 IO 任务数!
查看计算机cpu数的方法(java.lang)
Runtime.getRuntime().availableProcessors();