第三部分-并发设计模式34:WorkThread 设计模式

1.WorkThread 设计模式

可以有效避免频繁创建,销毁以及OOM问题

2.类比现实

类比车间的工作模式
车间工人,有活大家一起干,没活就聊聊天

image

车间里工人的数量是确定的

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();
posted @ 2021-06-11 16:17  SpecialSpeculator  阅读(114)  评论(0编辑  收藏  举报