2012-08-29 75 views
2

我在回答這個有趣的情況時遇到了this questionJava線程的意外行爲

嘗試這一塊的設計糟糕的代碼 -

import javax.swing.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

class abc extends JFrame implements ActionListener 
{ 

boolean button_clicked = false; 
JButton b1; 

abc(){ 
    this.setSize (400, 400); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    this.createUI(); 
} 

void createUI(){ 
    this.setLayout(null); 
    b1 = new JButton("Click here"); 
    b1.setSize(110,30); 
    b1.setLocation(10,210); 
    this.add(b1); 
    b1.addActionListener(this); 
} 

public boolean isButton_clicked() 
{ 
    return button_clicked; 
} 

public void setButton_clicked(boolean button_clicked) { 
    this.button_clicked = button_clicked; 
} 



public void actionPerformed(ActionEvent arg0) { 
    button_clicked = true; 
} 

} 

這裏的主要方法。

class tempMain extends JFrame 
{ 

public static void main(String[] args) throws Exception 
{ 
    abc temp = new abc(); 
    temp.setVisible(true); 
    while(true) 
    { 
    // Thread.sleep(200); 
     if(temp.isButton_clicked()) 
     { 
      JOptionPane.showMessageDialog(null, "Hello"); 
      temp.setButton_clicked(false); 
     } 
    } 
} 
} 

當我跑這我的Windows 7機器上,什麼都沒有發生至少約一分鐘(我沒有後等待)後,我點擊的按鈕。

現在,只是做一個小的變化 -

Thread.sleep(200); // uncomment this from the main. 

令人奇怪的是,它的工作原理,並顯示一條消息的JOptionPane。爲什麼消息不是第一次顯示?

回答

2

令人驚訝的是,它工作並顯示一個JOptionPane消息。爲什麼消息不是第一次顯示?

button_clicked沒有被標記爲volatile,正在從不同的線程比主線程更新。由於回調是由事件處理程序線程完成的,除非button_clicked被定義爲volatile boolean,否則主線程將不會看到更新。進入睡眠狀態可能會讓內存屏障被穿過,幸運的是主線程中的button_clicked被更新。

以下是一些更多reading about volatile以及爲什麼當我們處理多個線程時它很重要。


的另一個問題是,你有一個無限循環被噴涌消息System.out。這會在一段時間後完全阻止,因爲控制檯無法顯示快速停止檢查點擊的行。

+0

更新:我刪除了System.out.println()。即使沒有這個問題,問題仍然存在。 – CodeBlue

+0

您能否解釋一下 - 「由於回調是由事件處理程序線程完成的,主線程不會看到更新」?據我所知,主要是調用abc類的方法,並應始終能夠獲取button_clicked的最新值。 – CodeBlue

+1

但是我們正在討論可以在多個處理器上運行的多個線程,每個處理器都有自己的內存緩存。 Java需要被告知''button_clicked''需要在線程之間進行同步。這裏有一些閱讀:http://www.javamex.com/tutorials/synchronization_volatile.shtml – Gray