阻塞队列
什么情况下我们会使用阻塞队列:多线程并发处理,线程池!
学会使用队列!添加移除
四组API!
方式 | 抛出异常 | 有返回值不抛出异常 | 阻塞等待 | 超时等待 |
---|---|---|---|---|
添加 | add | offer | put | offer(e, int, TimeUnit) |
移除 | remove | poll | take() | poll() |
检测队首元素 | element | peek | - | - |
SynchroniousQueue 同步队列
容量为1,队列中元素被消费了才可以继续向队列中添加元素
线程池
线程池: 三大方法,七大参数,四种拒绝策略
线程池的好处:
-
- 降低资源的消耗,创建销毁线程十分浪费系统资源
-
- 提高响应的速度
-
- 方便管理
线程复用,可以控制最大并发数,管理线程
三大方法
阿里巴巴代码规范中提到
- newSingleThreadExecutor()
- newFixedThreadPool(int n)
- newCachedThreadPool()
ExecutorService executor = Executors.newSingleThreadExecutor();
七大参数
先分析一波三大方法的源码
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
发现本质都是调用的ThreadPoolExecutor,再看看这个类,其构造函数七个参数
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize, //最大核心线程池数大小
long keepAliveTime, //超时了没人调用会释放
TimeUnit unit, //超时单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory, //线程工厂,创建线程的,一般不会动
RejectedExecutionHandler handler) { //拒绝策略
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
手动创建线程池:
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
//银行满了,办理业务与等候区都满了还有人进来,不处理这个人的,抛出异常
threadPool.shutdown();
四种拒绝策略
new ThreadPoolExecutor.AbortPolicy()); //银行满了,办理业务与等候区都满了还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy()); //哪来的去哪里
new ThreadPoolExecutor.DiscardPolicy()); //队列满了,丢掉任务,不会抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy()); //队列满了,尝试去和最早的竞争,也不会抛出异常
我们如何去定义最大线程池的数量?
-
- CPU密集型:几核就是几,可以保证cpu的效率最高
-
- IO密集型:判断你的程序中十分耗费IO的线程,让其大于该值
获取CPU的核数
System.out.println(Runtime.getRuntime().availableProcessors());
四大函数式接口
函数式接口: 只有一个方法的接口
package java.lang;
@FunctionalInterface
public interface Runnable {
void run();
}
四大函数式接口:
- Function:函数式接口,有一个输入参数,有一个输出参数,对输入进行处理后输出
- Consumer: 消费型接口,只有输入没有返回值
- Supplier: 供给型接口,没有参数只有返回值
- Predicate: 断定型接口,有一个传入参数,返回值只能是布尔值
函数式接口:
public static void main(String[] args) {
Function<Integer, String> function = new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return integer.toString();
}
};
System.out.println(function.apply(10));
}
lambda表达式简化:
public static void main(String[] args) {
Function<Integer, String> function = str -> str.toString();
System.out.println(function.apply(10));
}