2013-12-21 100 views
1

當我編譯並運行StartThreads類時,我得到一個整數爲1到1000000的列表,並帶有false,並在最後打印出true; 現在我想知道的是爲什麼類class threadone在類MyVariables = true時應該打印實例變量時什麼都不打印? public class MyVariables {0} {0} {0} public boolean startApp = false; }線程方法未運行?

public class ThreadOne implements Runnable { 
Thread t; 
MyVariables x; 
public ThreadOne(MyVariables x) { 
    t = new Thread(this, "Thread One"); 
    this.x = x; 
} 
@Override 
public void run() { 
    while(this.x.startApp != false) { 
     System.out.println("Starting"); 
    } 
} 
public void start() { 
    t.start(); 
} 

} 

public class ThreadTwo implements Runnable { 
Thread t; 
MyVariables x; 
public ThreadTwo(MyVariables x) { 
    t = new Thread(this, "Thread One"); 
    this.x = x; 
} 
@Override 
public void run() { 
    synchronized(this.x) { 
     for(int i = 0; i <= 1000001; i++) { 
      if(i == 1000001) { 
       this.x.startApp = true; 
       System.out.println(this.x.startApp); 

      } 
      else { 
       System.out.println(this.x.startApp); 
       System.out.println(i); 
      } 
     } 
    } 

} 
public void start() { 
    t.start(); 
} 

} 


public class StartThreads { 

public static void main(String[] args) { 
    MyVariables a = new MyVariables(); 
    ThreadOne x = new ThreadOne(a); 
    ThreadTwo y = new ThreadTwo(a); 
    x.start(); 
    y.start(); 
} 

} 

回答

3

爲什麼ThreadOne應該像你說的那樣工作? while循環從未運行,而是因爲條件不成立而被跳過。我認爲你期望它等待某些東西變爲真,但它沒有任何作用,而是一旦它發現某個條件是錯誤的,就結束執行。

注意,這是醜陋的代碼:

while(this.x.startApp != false) { 

爲什麼狀態,而東西不假?這與爲真相同。 更好

while (x.startApp) { 

現在爲您的實際問題,也許你應該反而讓你的while循環:

while (!x.startApp) { 
    Thread.sleep(1); // surrounded with try/catch 
} 
System.out.println("Starting"); 

例如,

class ThreadOne implements Runnable { 
    Thread t; 
    volatile MyVariables x; 

    public ThreadOne(MyVariables x) { 
     t = new Thread(this, "Thread One"); 
     this.x = x; 
    } 

    @Override 
    public void run() { 
     while (!x.startApp) { 
     try { 
      Thread.sleep(1); 
     } catch (InterruptedException e) { 
     } 
     } 
     System.out.println("Starting"); 
    } 

    public void start() { 
     t.start(); 
    } 

} 

class ThreadTwo implements Runnable { 
    private static final int MAX_I = 10001; 
    Thread t; 
    volatile MyVariables x; 

    public ThreadTwo(MyVariables x) { 
     t = new Thread(this, "Thread One"); 
     this.x = x; 
    } 

    @Override 
    public void run() { 
     synchronized (this.x) { 
     for (int i = 0; i <= MAX_I; i++) { 
      if (i == MAX_I) { 
       this.x.startApp = true; 
       System.out.println(this.x.startApp); 

      } else { 
       System.out.println(this.x.startApp); 
       System.out.println(i); 
      } 
     } 
     } 

    } 

    public void start() { 
     t.start(); 
    } 

} 

public class StartThreads { 

    public static void main(String[] args) { 
     MyVariables a = new MyVariables(); 
     ThreadOne x = new ThreadOne(a); 
     ThreadTwo y = new ThreadTwo(a); 
     x.start(); 
     y.start(); 
    } 

} 

class MyVariables { 
    public volatile boolean startApp = false; 
} 

另外,我認爲你的布爾字段應當至少是不穩定的。


使用一個PropertyChangeListener和觀察者模式的另一種方法:

import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.beans.PropertyChangeSupport; 

public class StartThreads2 { 
    public static void main(String[] args) { 
     final MyVariables2 myVars2 = new MyVariables2(); 
     final RunOne runOne = new RunOne(); 
     final RunTwo runTwo = new RunTwo(myVars2); 

     myVars2.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent pcEvt) { 
      if (MyVariables2.START_APP.equals(pcEvt.getPropertyName())) { 
       if (pcEvt.getNewValue().equals(Boolean.TRUE)) { 
        new Thread(runOne).start(); 
       } 
      } 
     } 
     }); 

     new Thread(runTwo).start(); 
    } 
} 

class MyVariables2 { 
    public static final String START_APP = "start app"; 
    private volatile boolean startApp = false; 
    private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this); 

    public boolean isStartApp() { 
     return startApp; 
    } 

    public void setStartApp(boolean startApp) { 
     boolean oldValue = this.startApp; 
     boolean newValue = startApp; 
     this.startApp = startApp; 
     pcSupport.firePropertyChange(START_APP, oldValue, newValue); 
    } 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     pcSupport.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener listener) { 
     pcSupport.removePropertyChangeListener(listener); 
    } 
} 

class RunOne implements Runnable { 
    @Override 
    public void run() { 
     System.out.println("Starting RunOne"); 
    } 
} 

class RunTwo implements Runnable { 
    private static final int MAX_I = 10001; 
    private MyVariables2 myVars2; 

    public RunTwo(MyVariables2 myVars2) { 
     this.myVars2 = myVars2; 
    } 

    @Override 
    public void run() { 
     for (int i = 0; i <= MAX_I; i++) { 
     System.out.println("startApp: " + myVars2.isStartApp()); 
     System.out.printf("i: %05d%n", i); 
     } 

     myVars2.setStartApp(true);  
     try { 
     Thread.sleep(10); 
     } catch (InterruptedException e) {} 
     System.out.println("startApp: " + myVars2.isStartApp()); 
    } 
} 
+0

如果我改變而statment爲「如果(!this.x.startApp)」,它仍然沒有顯示,所以我不要不知道線程是否工作? –

+0

@JohnArckai:查看最新編輯 –

+1

while循環從不「退出」。它從未輸入時如何退出?它會在運行主體之前檢查條件,並且條件如您所說的那樣是假的,但它從不輸入,因此無法退出。我會理解這是否是一段時間。另外,如果你向他提到this.x.startApp需要在他的while循環運行時設置爲true,那最好。這是OP代碼唯一的錯誤。除此之外,在這種情況下沒有理由同步。 – Brandon