第三部分-并发设计模式34:WorkThread 设计模式
1.WorkThread 设计模式
可以有效避免频繁创建,销毁以及OOM问题
2.类比现实
类比车间的工作模式
车间工人,有活大家一起干,没活就聊聊天
车间里工人的数量是确定的
3.编程世界映射车间的套路呢
如何实现Worker Thread模式
阻塞队列做任务池,创建固定数量的线程消费阻塞队列。
这个方案就是线程池方案
4.线程池方案,解决Thread-Per-Message的问题
伪代码
ExecutorService es = Executors
.newFixedThreadPool(500);
final ServerSocketChannel ssc =
ServerSocketChannel.open().bind(
new InetSocketAddress(8080));
//处理请求
try {
while (true) {
// 接收请求
SocketChannel sc = ssc.accept();
// 将请求处理任务提交给线程池
es.execute(()->{
try {
// 读Socket
ByteBuffer rb = ByteBuffer
.allocateDirect(1024);
sc.read(rb);
//模拟处理请求
Thread.sleep(2000);
// 写Socket
ByteBuffer wb =
(ByteBuffer)rb.flip();
sc.write(wb);
// 关闭Socket
sc.close();
}catch(Exception e){
throw new UncheckedIOException(e);
}
});
}
} finally {
ssc.close();
es.shutdown();
}
5.创建线程池的正确姿势
java线程池可以避免无限制的创建线程导致OOM
也可以避免无限制的接受任务导致OOM(线程池指定游街队列接受任务)
当请求量大于有界队列容量时,就合理的拒绝请求。同时创建时,要给线程赋予一个业务相关的名字
范例
ExecutorService es = new ThreadPoolExecutor(
50, 500, 60L, TimeUnit.SECONDS,
//注意要创建有界队列
new LinkedBlockingQueue(2000),
//建议根据业务需求实现ThreadFactory
r->{
return new Thread(r, "echo-"+ r.hashCode());
},
//建议根据业务需求实现RejectedExecutionHandler
new ThreadPoolExecutor.CallerRunsPolicy());
6.注意事项
提交到相同线程池中的任务一定是相互独立的,最好不要相互依赖
7.总结
Worker-Thread 其实也是一种分工模式
Thread-Pre-Message 类比现实中的委托他人办理
Worker-Thread 类似车间工人的工作模式
Worker-Thread 能避免线程频繁创建,销毁,而且可以限制线程的最大数量。java语言可以直接使用线程池实现WorkerThread模式,线程池是一个基础及优秀的工具类。大厂是不允许使用new Thread()来创建线程的,必须用线程池。
8.扩展
// 只有一个线程的线程池
ExecutorService pool = Executors.newSingleThreadExecutor();
原创:做时间的朋友