2017-08-30 44 views
-1

虽然在工作线程中使用一个简单的互斥锁和条件变量,但我的程序会收到一些罕见且零星的线程匮乏错误,但我想阻止它。Java中的“无饥饿”实现

以下是我正在做的一个简单的例子。有4个工作线程调用“Producer”和一个调用prod.getTasks()的主线程。

此代码是“无死锁”,但由于错误,显然不是“无饥饿”。

当我拿到检测线程饥饿或时钟飞跃(管家三角洲=1m18s317ms137μs765ns)错误是:

A)由于生产者线程是坐在一个等待状态的时间过长? (我不这么认为,因为我认为一个线程在准备好使用之前可能会等待任意一段时间,肯定会超过1分钟)。 B)因为其中一个等待工作者线程已经被多次传递了吗?

基本上任何好的提示,以帮助使这个饥饿免费将不胜感激。

class Producer implements Runnable 
{ 
    private static ArrayList<Task> arrTasks = new ArrayList<Task>(); 

    void getTasks() 
    { 
     Task t = getTask(); // get Tasks from a producer specific recordset.  
     synchronized (arrTasks) 
     { 
      arrTasks.add(t); 
      arrTasks.notify(); 
     } 
    } 

    void run() 
    { 
     while (true) 
     { 
      Task t = null; 

      synchronized (arrTasks) 
      { 
       if (arrTasks.size() == 0) 
        arrTasks.wait(); 

       if (arrTasks.size() > 0) 
        t = arrTasks.remove(0); 
      } 

      if (t != null) 
       processTask(t); 

      if (mExit) 
       break; 
     } 
    } 
} 
+1

代码不完整。什么是's_ptTasks'?另外,你在一个对象上wait(),在另一个对象上notify()。这个可以吗? –

+0

@RomanPuchkovskiy:我的不好..我编辑它。 – paiego

+0

@NathanHughes这是对实际代码的简化,它可以正确使用保护块。我也知道我可以使用更高级别的服务来处理并发。这只是一个关于饥饿的问题。 – paiego

回答

0

生产者/消费者模式总是要么饿死,要么过载,要么毫无意义。这不是一个性能模式,它用于抽象。

如果您使用的concurrent BlockingQueue允许您删除所有​​,那么您的代码可以变得更容易。

+0

实际的实现既没有超载,也没有意义,也没有经常饿死。它每晚都有效地运行数百万条记录,并且只有一次显示出饥饿。如果BlockingQueue也使用防护块,我也不会感到惊讶。 – paiego