2013-01-31 194 views
0

我有一個模塊,它可以處理數千個事務。每筆交易都有多個階段可以完成。該模塊在多線程模式下執行。 我們已經爲它可以創建的線程數量定義了限制(硬編碼)(按服務器利用率限制)。如何避免多線程程序因線程等待而被阻塞

現在我們來到翻過一個情況,即線程可能需要等待一段時間(可能超過24小時)。由於我們的線程數量有限,並且如果所有線程都等待超過24小時,這完全阻止了應用程序。

我需要的是在這裏,我應該怎麼重用線程是在等待等待24小時。 如果線程正在進入等待模式,我需要重新使用該線程進行anather事務,並且當原始等待結束時,重新啓動保留它的原始事務。

我希望上面詳細描述有助於u到理解問題。

+1

你在使用'ExecutorService'還是一些等價的東西?每個「交易」應該是一項應該能夠執行的任務。如果由於任何原因,交易無法完成,則應將其過帳到未決隊列。您應該有一個獨立的線程監視此待處理隊列中是否有任何準備好執行的任務,並將其發佈到執行程序服務以在下一個可用線程上執行。聽起來像是對現有架構的輕微重新設計...... – Nim

+0

當你說「線程將要等待幾個小時」時,你的意思是「它會睡眠x小時,然後再試一次」或「它正在積極輪詢某個事件從現在到幾個小時之間的任何時間都可能發生「?對於後一種情況,我希望有一個序列化解決方案。 – SJuan76

回答

0

如果你的系統中有長時間的延誤,做的最好的是有更多的線程。如果你想限制同時運行的線程的數量,你可以使用許可,例如一個信號量,每當你阻塞操作時釋放,並在阻塞結束時重新獲得。這可確保您一次運行的線程數量有限,但可讓您輕鬆地在多項任務之間切換。

public abstract class LimitedTask implements Runnable { 
    static final Semaphore PERMITS = new Semaphore(Runtime.getRuntime().availableProcessors()); 

    @Override 
    public final void run() { 
     try { 
      PERMITS.acquire(); 
     } catch (InterruptedException e) { 
      System.err.println("Task " + getClass() + " cancelled before it was started."); 
      return; 
     } 
     try { 
      runTask(); 
     } finally { 
      PERMITS.release(); 
     } 
    } 

    protected abstract void runTask(); 

    protected void runBlockingTask(Runnable runnable) { 
     PERMITS.release(); 
     try { 
      runnable.run(); 
     } finally { 
      PERMITS.acquireUninterruptibly(); 
     } 
    } 
} 

在這個例子中,你可以有儘可能多的這些,但只有有限的數字將在PERMIT區域內。這些任務還可以調用runBlockingTask()來允許它執行阻塞任務,但允許另一個線程在阻塞時運行。