2013-12-11 32 views
2

我已經在這裏討論了關於java多線程的幾乎所有問題,但是我不太明白我的理解是否正確。在這裏調用'wait'和'notify'

我希望瞭解操作順序是否按照下面的描述進行操作。

import javax.swing.*; 
import java.awt.FlowLayout; 
import java.awt.event.*; 

class Runner implements Runnable{ 
    long count = 0; 
    JLabel label; 
    boolean paused = false; 

    public Runner(JLabel label){ 
     this.label = label; 
    } 

    public void run(){ 
     while(true){ 
      try { 
       if(paused){ 
        synchronized(this){ 
         wait(); 
        } 
       } 
      } catch(InterruptedException e) {} 
       count++; 
       label.setText(Long.toString(count)); 
       if(Thread.interrupted()) 
        return; 
     } 
    } 

    synchronized void pause_counting(){ 
     paused = true; 
    } 

    synchronized void start_counting(){ 
     paused = false; 
     notifyAll(); 
    } 
} 

public class ThreadRace extends JApplet{ 
    boolean running = true; 
    Thread thread; 

    @Override 
    public void init(){ 
     final JPanel panel = new JPanel(); 
     panel.setLayout(new FlowLayout()); 

     JLabel threadProgress = new JLabel("0"); 
     final Runner runner = new Runner(threadProgress); 
     thread = new Thread(runner); 
     thread.start(); 

     panel.add(threadProgress); 

     JButton toggle = new JButton("Stop"); 
     toggle.addActionListener(new ActionListener() { 
      @Override 
      synchronized public void actionPerformed(ActionEvent e) { 
       System.out.println("Running: " + running); 
       if(running){ 
        runner.pause_counting(); 
       } else { 
        runner.start_counting();  
       } 
       running = !running; 
      } 
     }); 
     panel.add(toggle); 

     add(panel); 
    } 

    public void stop(){ 
     thread.interrupt(); 
    } 
} 

這是如何工作的?

  1. 當我調用方法pause_counting()時,我將暫停設置爲false。
  2. 在run()的內部,我抓住了synchronized(this) { ... }塊內的對象runner的鎖。
  3. 當我打電話給this.wait()時,我釋放了我剛纔擁有的同一把鎖,並進入WAITING狀態。
  4. 在這一點上,任何其他方法可以自由地做任何事情runner(!)
  5. 我最終打電話給start_counting()
  6. 這使線程回到RUNNING狀態,並從wait()語句之後繼續。雖然它仍是synchronized(this)塊內,它就會被持有鎖的
  7. 然而,一旦離開塊,它釋放鎖,並繼續執行

我敢肯定有一些缺陷在我理解。

幫助? :(

+0

不是一個答案,但相關(和**強烈推薦**):http://blog.smartbear.com/programming/why-johnny-cant-write-multithreaded-programs/ –

+0

你的第一個錯誤是在不同的同步「Runner」的實例。 –

+0

我理解,理想情況下,所有三個應該在同一個顯示器上同步。但是,我明確希望瞭解使用'this'的效果。也許這不完全是最好的例子...... – peteykun

回答

2

這是它如何工作?

是,您的所有陳述都與一些調整真(見下文)。

不過,目前在你的程序中的錯誤。因爲線程的paused內​​塊的測試,你需要確保pausedvolatile提供內存同步。

volatile boolean paused = false 

這對於JLabel陣列也是必要的。任何時候你有一個線程正在改變共享變量,需要進行內存同步。


當我調用該方法pause_counting(),我設置停下來假的。

是的。更新paused這裏沒關係,因爲它在​​方法。

在run()的內部,我鎖定了同步(this){...}塊內的對象runner [i]。

只有paused爲真。由於您正在測試​​塊之外的paused,所以paused需要爲volatile以確保線程之間的內存同步。

當我打電話給this.wait()時,我釋放了我剛纔佔據的同一個鎖並進入WAITING狀態。

沒錯。

在這一點上,任何其他方法是免費的這個亞軍做什麼[I](!)

那麼它是免費之前,但現在的解除鎖定它可以做的東西請撥打​​方法,不要阻止。

我最終打電話給start_counting()。

沒錯。這要求notifyAll()

這使線程回到RUNNING狀態,並從wait()語句之後繼續。雖然它仍然是同步的(這個)塊中,它被持有鎖的

那麼首先它使線程進入BLOCKED狀態,直到的start_counting()呼叫者留下的是方法和釋放鎖。

然而,一旦離開塊,它釋放鎖,並繼續執行

權。

+0

謝謝。 :) 在'synchronized(this){...}'塊中包含'paused'的檢查將實現相同的目標,對吧? – peteykun

+0

是的,這將工作@SohamPal。你應該在'synchronized'塊中更新'JLabel',或者在'Runner'上使它成爲'volatile'字段。 – Gray

相關問題