2017-04-18 91 views
1

我有兩個線程。第一個更改變量Data的值。如果它的值已經改變,第二個打印值。我試圖做的第二個線程只是打印每次該變量的值改變,但我沒有達到成功。有人可以幫助我嗎?如何通知第二個線程變量的變化

線程1

class someservice{ 

    volatile int data; 
    Boolean Flag = false; 

    public void mymethod(){ 

     flag = true; 

     for (Integer i = 1; i < sheet.getRows(); i++) { 

      data = someMethod(); //this method when called return a new 
            //value 
     } 

     flag = false; 
     ... 
    } 
    } 

線程2

Promise p = task { 
      try { 

       while (true) { 

        if (engineService.getFlag()) { 

          print(someservice.data);        

        }else{ 
         break; 
        } 
       } 
      } catch(Throwable t) { 
       ... 
      } 
     } 
+0

當您更改變量你設置'engineService.getFlag()''到TRUE'?我沒有在你的代碼中看到它... – brso05

+0

你是在正確的軌道上...而是承諾使用可調用的,未來... –

回答

0

既然你提到的承諾,我推斷你所熟悉的未來/承諾在+ C++ 11

在Java有一個類似的方法,未來可以調用...

public class HW5 { 
    public static void main(String[] argv) throws InterruptedException, ExecutionException { 
    FutureTask<Boolean> myFutureTask = new FutureTask<>(new Callable<Boolean>() { 

     @Override 
     public Boolean call() throws Exception { 
     // implement the logic here and return true if everything was 
     // ok, false otherwise. 
     Thread.sleep(5000); 
     System.out.println("dddd"); 
     return System.currentTimeMillis() % 2 == 0; 
     } 
    }); 

    ExecutorService executor = Executors.newFixedThreadPool(1); 
    executor.execute(myFutureTask); 
    Boolean result = myFutureTask.get(); 
    System.out.println("Done!"); 
    } 
} 

FutureTask中的一個類需要一個可調用的對象,可以在其作業完成後返回一個對象...爲了執行Future任務,您可以使用Executor服務,特別是調用方法execute,因爲您需要等待該線程來完成這項工作,然後是必要的,你叫的Future.get,將基本塊主線程等到將來完成,以驗證結果,剛讀變量結果 ..

0

你可以在線程中使用notify()和notifyAll()方法。看看這個鏈接:https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

public synchronized void guardedJoy() { 
    // This guard only loops once for each special event, which may not 
    // be the event we're waiting for. 
    while(!joy) { 
     try { 
      wait(); 
     } catch (InterruptedException e) {} 
    } 
    System.out.println("Joy and efficiency have been achieved!"); 
} 


public synchronized notifyJoy() { 
    joy = true; 
    notifyAll(); 
} 
+0

不要寫空的catch塊。並且不要忽略InterruptedException;中斷是來自另一個線程的顯式請求,用於停止正在執行的操作並正常退出。忽略它會使您的代碼成爲流氓線程。 – VGR

+0

同意。這是我引用的Oracle鏈接的一個片段。我認爲他/她不會逐字使用代碼。 :) – Matt

0

你要查找有關併發編程更多的數據,我可以告訴你,現在的一些基礎知識,好了,不那麼這樣基本的,但我會盡我所能:

在這裏,你有一個監視器,它是一個抽象的概念,在簡歷中,監視器是一個 類與所有它的使用 法「syncronized」 作爲改性劑,它意味着, 只有 一個線程 可以訪問 方法 一次。因此, 在 顯示器 變量 你 要打印, 並告訴你,如果 變量 是modified.Finally, 可以 看到 最重要的事情「標誌」, 時, 「等待()」和「通知()」方法, 那些方法 停止線程,或「播放」 他們再次。

您在

的PRINTVALUE()方法在這裏問 ,如果您的變量被改變,如果變量was'nt變化,把THEAD與wait()方法來睡覺,而當其他

方法changeValue()被執行時,值被修改,和notify()方法被調用時,喚醒線程,因此,做這一切,你能保證三兩件事:

安全性:這意味着線程將完成你想要的操作 沒有死鎖:意味着被放置的線程睡覺,將來會清醒。 互斥體:意味着只有一個線程正在執行關鍵代碼,例如,操作。 「++」不是原子的,被細分爲更多的一個動作,創建一個局部變量,讀取var,sum和asign,所以,如果多於一個線程在遊戲中,則該值可能不是連續的,例如:

i = 0; 
i ++; 
output: 1; 
output: 2; 
output: 3; 
output: 5; 
output: 4; 
output: 7; 

可能發生,即使如此,因爲有一個以上的線程中執行,這將在未來的代碼發生。那麼,這是有幾個線程,或多或少

public class Monitor { 

     private int value = 0; 
     public static boolean valueHasChanged = false; 

     public synchronized int changeValue(int newValue){ 
      this.value = newValue; 
      Monitor.valueHasChanged = true; 
      this.notify(); 
      return this.value + 1; 
     } 

     public synchronized void printValue(){ 
      while(!Monitor.valueHasChanged){ 
       try { 
        this.wait(); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(this.value); 
      Monitor.valueHasChanged = false; 
     } 

     public static void main(String[] args) { 
      Monitor ac = new Monitor(); 

      BClass t1 = new BClass(ac); 
      AClass t2 = new AClass(ac); 

      t1.start(); 
      t2.start(); 
     } 

     public int getValue() { 
      return this.value; 
     } 
    } 

現在線程編程的方式:

public class AClass extends Thread{ 

     private Monitor ac; 

     public AClass(Monitor ac) { 
      this.ac = ac; 
     } 

     @Override 
     public void run() { 
      while(true){ 
       this.ac.printValue(); 
      } 
     } 

    } 

最後:

public class BClass extends Thread{ 

     private Monitor ac; 

     public BClass(Monitor ac) { 
      this.ac = ac; 
     } 

     @Override 
     public void run() { 
      int v = 0; 
      while(true){ 
       this.ac.changeValue(v); 
       v++; // this sum is not secure, if you want to print an 
        // ascending order, the code is diferent, I will show in 
        // above. 
      } 
     } 

現在,如果你想要一個有序打印:

顯示器看起來像:

public class Monitor { 

     private int value = 0; 
     public boolean valueHasChanged = false; 
     private boolean hasPrint = true; 

     public synchronized void changeValue(int newValue) { 
      this.value = newValue; 
      this.valueHasChanged = true; 
      this.notify(); 
     } 

     public synchronized void changeValuePlusOne() { 
      while (!hasPrint) { 
       try { 
        this.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      this.value++; 
      this.valueHasChanged = true; 
      this.hasPrint = false; 
      this.notifyAll(); 
     } 

     public synchronized void printValue() { 
      while (!this.valueHasChanged) { 
       try { 
        this.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(this.value); 

      this.valueHasChanged = false; 
      this.hasPrint = true; 
      this.notifyAll(); 
     } 

     public static void main(String[] args) { 
      Monitor ac = new Monitor(); 

      BClass t1 = new BClass(ac); 
      AClass t2 = new AClass(ac); 

      t1.start(); 
      t2.start(); 
     } 

     public int getValue() { 
      return this.value; 
     } 

    } 

而且主題:

public class BClass extends Thread{ 

     private Monitor ac; 

     public BClass(Monitor ac) { 
      this.ac = ac; 
     } 

     @Override 
     public void run() { 
      while(true){ 
       this.ac.changeValuePlusOne(); 
      } 
     } 

     } 

其他線程的外觀等於:

public class AClass extends Thread{ 

    private Monitor ac; 

    public AClass(Monitor ac) { 
     this.ac = ac; 
    } 

    @Override 
    public void run() { 
     while(true){ 
      this.ac.printValue(); 
     } 
    } 

}