2017-01-08 96 views
-1

我有一個多線程多對象系統,其中我有一個manager和多個workers。我需要的workersmanager同步,就像這樣:多個對象之間的java線程同步

manager不做某事,使爲了使workers,然後讓並行workers運行,相互獨立的。當他們完成這一輪時,他們必須等待manager給他們新的任務或訂單。 manager只有在所有workers都完成了他們以前的工作後纔會發出新訂單。

我需要使用線程來實現它,以避免忙等待。然而同步是令人困惑的。

有什麼想法?

+0

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html – shmosel

+1

我有很多想法;我可以給你一個每日費率。否則,寫一些代碼並找出你有什麼問題;然後張貼在這裏尋求幫助。我們不是代碼編寫服務。提示:查看['CyclicBarrier'](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html)。 –

+0

@BoristheSpider我當然沒有/不想寫代碼服務。只是一個提示。 CyclicBarrier解決了這個問題。 – Farzad

回答

0

作爲@boristhespider建議,我使用CyclicBarrier爲managerworkers

在每個worker完成其任務後,它會調用barrier.await()。然後爲manager,我檢查是否barrier.getNumberWaiting()==NumWorkers。如果是true,則更新每個worker的任務,然後調用barrier.await()

+0

如何檢查'barrier.getNumberWaiting()'而無需等待管理器? –

1

編輯︰我錯過了一個重要的部分,說新的任務應該只有當所有完成。因此使用LinkedBlockingQueue不是最佳解決方案。我建議使用CyclicBarrier boris-the-spider推薦。

您可以使用LinkedBlockingQueue

設置一個固定容量。

manager可以put任務,而workers可以使用功能take等待。

+0

分類:我想如果你有'n'任務和'n'工作人員 - 任務需要足夠的時間來運行 - 那麼當你將'n'任務發佈到'BlockingQueue'上時,每個工作人員都會執行一項任務,處理它。但這並不能解決主人等待工人的問題。使用非常簡單的['ExecutorService.invokeAll'](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAll(java。 util.Collection))。 –

+0

主人可以通過查看'queue.size()> = n'和睡眠 - 等一下等待工人。或者工作人員可以表明他們的狀態,有很多方法可以做到。 –

+0

這不行,除非工人把東西放回_another_隊列 - 所以你需要兩個隊列。我不是說你的方法不行,我只是說你正在重新發明輪子;當涉及到併發代碼時,這通常是一個非常糟糕的主意。 'ExecutorService'代碼是JDK的一部分,所以經過了很好的測試。它確實需要什麼...... –

0

保持2個阻塞隊列 1.任務 2.免費工人

讓工人通過回調,這將它們添加到自由工作隊列

內部管理通知管理器線程可以檢查工可用。

快速實施

import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.LinkedBlockingQueue; 

public class ManagerWorker { 
    public static void main(String[] args) { 

     ExecutorService service = Executors.newCachedThreadPool(); 
     BlockingQueue<String> taskQueue = new LinkedBlockingQueue<>(); 

     Manager m = new Manager(5, taskQueue); 
     service.submit(m); 

     for (int i = 0; i < 5; i++) { 
      service.submit(new Worker(m, taskQueue)); 
     } 

    } 
} 

class Manager implements Runnable { 

    int workerCount; 
    BlockingQueue<Worker> workerqueue = new LinkedBlockingQueue<>(); 
    BlockingQueue<String> taskQueue; 

    public Manager(int workerCount, BlockingQueue<String> taskQueue) { 
     this.workerCount = workerCount; 
     this.taskQueue = taskQueue; 
    } 

    public void callBackForFreeNotification(Worker worker) { 
     workerqueue.add(worker); 
    } 

    @Override 
    public void run() { 
     while (true) { 
      try { 
       int i = 0; 
       while (i < workerCount) { 
        workerqueue.take(); 
        i++; 
       } 

       System.out.println("Manager Worker available"); 

       // add task to task queue here 
       for (int j = 0; j < workerCount; j++) { 
        taskQueue.add("task"); 
       } 
       System.out.println("Manager task added"); 
      } catch (InterruptedException e) { 

       e.printStackTrace(); 
      } 
     } 
    } 

} 

class Worker implements Runnable { 

    private Manager manager; 
    private BlockingQueue<String> taskQueue; 

    public Worker(Manager manager, BlockingQueue<String> taskqueue) { 
     this.manager = manager; 
     this.taskQueue = taskqueue; 
    } 

    @Override 
    public void run() { 
     while(true){ 


     try { 

      System.out.println("Worker - i have no work"); 
      manager.callBackForFreeNotification(this); 
      taskQueue.take(); 
      System.out.println("Worker working"); 
      Thread.sleep(2000); 
      System.out.println("Worker Done with work"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     } 
    } 

}