2015-08-15 67 views
0

以下程序會創建生成隨機數的線程。使用監視器類同步Java中的線程

我如何更改Monitor所以它將控制線程的打印方式將按每個線程ID的順序打印?

解決方案如「調用run方法而不是start」不被接受。

給出的歸類是:

public class Main { 
    public static void main(String[] args) { 
     Monitor mon = new Monitor(); 
     for (int i = 0; i < 20; i++) 
      new T(i, mon).start(); 

     System.out.println("Finished"); 
    } 
} 

public class Monitor { 

    public void print(int id, int num) { 
     System.out.println("id=" + id + " num=" + num); 
    } 
} 

public class T extends Thread { 
    private int id; 
    private Monitor mon; 

    public T(int i, Monitor m) { 
     id = i; 
     mon = m; 
    } 

    private int calc() { 
     int num = 0; 
     for (int i = 0; i < 10; i++) 
      num = num + (int) (Math.random() * 10); 
     return num; 
    } 

    public void run() { 
     int num = calc(); 
     mon.print(id, num); 
    } 
} 
+0

什麼問題? –

+0

看起來像作業 – kervin

+0

我同意,但我認爲這很有趣,主要是因爲只有'Monitor'可以改變的限制。使其同步或應用任何其他類型的鎖定可能更有可能按順序打印線程ID,但不能保證它。 –

回答

3

你只需要線程試圖打印等待和阻塞,直到它的ID是預期的ID:

public class Monitor { 

    private final Object lock = new Object(); 
    private int expectedId = 0; 

    public void print(int id, int num) { 
     synchronized (lock) { 
      while (id != expectedId) { 
       try { 
        lock.wait(); 
       } 
       catch (InterruptedException e) { 
        return; 
       } 
      } 
      System.out.println("id=" + id + " num=" + num); 
      expectedId++; 
      lock.notifyAll(); 
     } 
    } 
} 
+0

我來到一個沒有鎖定的解決方案(請參閱我的答案)。我錯過了什麼嗎?對它有什麼好處? –

+0

你只是使用'this'作爲鎖而不是使用專用對象。這並沒有太大的改變...除了我的解決方案中沒有其他的代碼也使用我的鎖來同步一個完全不同的東西。我也不明白THREADS_NUM常量的意義,特別是考慮到你將它設置爲10,儘管你有20個線程。 –

+0

謝謝,你讓我更清楚地理解了一些事情。 –

1

對於任務怪只有怪的解決方案可以提出。我的版本會是這樣的:

import java.util.Map; 
import java.util.Map.Entry; 
import java.util.TreeMap; 

public class Monitor { 
    Map<Integer, Integer> map = new TreeMap<>(); 

    public synchronized void print(int id, int num) { 
     map.put(id, num); 
     if(map.size() == 20) { 
      for(Entry<Integer, Integer> entry : map.entrySet()) 
      System.out.println("id=" + entry.getKey() + " num=" + entry.getValue()); 
     } 
    } 
} 

它解決了您的問題。諸如「取決於線程數量」的異議不被接受。

+0

騙子! :-)我必須承認這是我頭腦中的第一個解決方案。 –

+0

@JBNizet,雖然你的版本好多了,但是,投票:-) –

0

通過@ JBNizet的答案,我來到了這個解決方案的啓發(使用this爲鎖):

public class Monitor { 
    private int currId = 0; 

    public synchronized void print(int id, int num) { 
     while (id != currId) { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     System.out.println("id=" + id + " num=" + num); 
     currId++; 
     notifyAll(); 
    } 
}