2015-03-31 120 views
1

有時我的服務器收到一個請求,可能導致提交1000個任務。在使用線程池時,我不希望線程池中超過15個線程用於來自同一請求的任務。在Java ExecutorService中如何設置請求消耗的最大線程數

如果我不這樣做,它會導致其他請求的飢餓。

關於如何實現這一點的任何建議。

+2

你的問題聽起來有點不清楚。通常使用ExecutorService(實質上是一個線程池)來避免在運行時創建線程;然而,你說你的任務可以通過自己創建線程。你在使用ForkJoinPool嗎?否則,請告訴我們您的使用案例。 – 2015-03-31 05:00:33

+0

一致。我試圖澄清。沒有請求不產生新的線程。他們有時會產生太多的任務來執行。 – Ram 2015-03-31 05:09:32

+0

創建一個'threadpoolexecutors'隊列,並且每次檢查可用性 – 2015-03-31 05:29:33

回答

0

有2例爲創建了太多的要求:

  1. 您的系統真的需要這麼多的要求進行處理。如果是這種情況,除了嘗試獲得更好的硬件和調整個人任務的性能,沒有辦法。

  2. 你的任務實際上可以被合併和合並(我覺得這是你的情況)。如果是這種情況,您可以嘗試一下我得到的工作人員,以確保只有1個執行被觸發,因爲每個請求都會將任務放入ExecutorService。 IDispatcher基本上是我的ExecutorService

/** 
 
* This class ensures the given task is only dispatched once in the dispatcher. 
 
* 
 
* @author Alex Suo 
 
* 
 
*/ 
 
public class DispatchOnceWorker implements IDispatchWorker { 
 

 
    /** Logger of the class. */ 
 
    private static final Logger LOG = LoggerFactory.getLogger(DispatchOnceWorker.class); 
 

 
    /** The key of task. */ 
 
    private final String key; 
 

 
    /** The actual task to be dispatched. */ 
 
    private final Runnable taskWrapper; 
 

 
    /** The dispatcher working on. */ 
 
    private final IDispatcher dispatcher; 
 

 
    /** The counter for task scheduling count. */ 
 
    private final AtomicInteger counter = new AtomicInteger(); 
 

 
    /** 
 
    * Constructor. 
 
    * 
 
    * @param key The dispatcher key for the task. 
 
    * @param task The actual task to be executed/dispatched. 
 
    * @param dispatcher The dispatcher working on. 
 
    */ 
 
    public DispatchOnceWorker(final String key, final Runnable task, final IDispatcher dispatcher) { 
 
     this.key = key; 
 
     this.dispatcher = dispatcher; 
 

 
     this.taskWrapper = new Runnable() { 
 

 
      @Override 
 
      public void run() { 
 
       try { 
 
        counter.set(1); 
 
        task.run(); 
 
       } catch (Exception e) { 
 
        LOG.error("Error executing on dispatch key " + key, e); 
 
       } finally { 
 
        if (counter.decrementAndGet() > 0) { 
 
         dispatcher.dispatch(key, this); 
 
        } 
 
       } 
 
      } 
 

 
     }; 
 
    } 
 

 
    @Override 
 
    public void dispatch() { 
 
     if (counter.getAndIncrement() == 0) { 
 
      dispatcher.dispatch(key, taskWrapper); 
 
     } 
 
    } 
 

 
}

0

您應該基準多少個請求您的應用程序可以同時處理,以便請求可以被正常處理。一般來說,我們使用工作隊列來處理這些場景。

片段從書中的「Java併發編程實踐」:

Requests often arrive in bursts even when the average request rate is fairly stable. Queues can help smooth out transient bursts of tasks, but if tasks continue to arrive too quickly you will eventually have to throttle the arrival rate to avoid running out of memory.[4] Even before you run out of memory, response time will get progressively worse as the task queue grows 

說了這麼多,你的情況可能是,你可以使用線程每個請求模型或threadpool-per-request模型。