1. 程式人生 > 其它 >併發設計模式34:WorkThread 設計模式

併發設計模式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();