2013-01-31 195 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()来允许它执行阻塞任务,但允许另一个线程在阻塞时运行。