2012-07-21 48 views
6

在我的android程序中,一個Activity調用一個新的表面視圖類,然後又調用一個新的線程類。我希望能夠通過活動的onPause和onResume方法將值傳遞給線程類,以便我可以暫停並恢復線程。我知道傳遞這些數據的唯一方法是創建一個新實例,它將創建一個不同的線程。我應該怎麼做而不創建一個新的線程實例?將活動中的值傳遞給已創建線程後的線程

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(new GameSurface(this)); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
      //Would like to pass this value 
      int state = 1; 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
      //Would like to pass this value 
      int state = 2; 
} 
+0

我已經更新了我的答案,2個類和'AtomicInteger'的工作實現。問候 – Killrawr 2012-07-24 03:12:24

回答

4

上併發

在併發傳遞值一點背景是容易的部分。查看AtomicInteger數據類型(更多信息here)。原子性也意味着All or nothing。這種數據類型不一定在線程或處理器之間發送數據(就像你使用mpi一樣),但它只是在共享內存上共享數據。

但什麼是原子操作?....

原子操作是作爲一個獨立的工作單元,不受其他業務干擾的可能性進行操作。

在Java中,語言規範保證讀取或寫入變量是原子的(除非變量的類型是long或double)。龍和雙只有原子的,如果他們聲明爲volatile ....

信貸(Java Concurrency/Multithreading - Tutorial拉爾斯沃格爾)

我強烈建議你閱讀這一點,它涵蓋了從atomicitythread poolsdeadlocksthe "volatile" and "synchronized" keyword


開始授課這將執行一個新的線程(它也可以作爲我們Main Thread簡稱)。

import java.util.concurrent.atomic.AtomicInteger; 
/** 
* @author Michael Jones 
* @description Main Thread 
*/ 
public class start { 
    private AtomicInteger state; 
    private Thread p; 
    private Thread r; 
    /** 
    * constructor 
    * initialize the declared threads 
    */ 
    public start(){ 
     //initialize the state 
     this.state = new AtomicInteger(0); 
     //initialize the threads r and p 
     this.r = new Thread(new action("resume", state)); 
     this.p = new Thread(new action("pause", state)); 
    } //close constructor 

    /** 
    * Start the threads 
    * @throws InterruptedException 
    */ 
    public void startThreads() throws InterruptedException{ 
     if(!this.r.isAlive()){ 
      r.start(); //start r 
     } 
     if(!this.p.isAlive()){ 
      Thread.sleep(1000); //wait a little (wait for r to update)... 
      p.start(); //start p 
     } 
    } //close startThreads 

    /** 
    * This method starts the main thread 
    * @param args 
    */ 
    public static void main(String[] args) { 
     //call the constructor of this class 
     start s = new start(); 
     //try the code 
     try { 
      s.startThreads(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } //start the threads 
    } //close main 

} //close class start 

因爲整數是原子,你也可以找回任何地方,但在開始main methodSystem.out.println("[run start] current state is... "+state.intValue());(如果您想從main method找回它,你將不得不建立一個setter /吸氣,就像我在Action類這樣做)

行動這是我們在行動主題(它也可以被稱爲我們的Slave Thread)。

import java.lang.Thread.State; 
import java.util.concurrent.atomic.AtomicInteger; 

/** 
* @author Michael Jones 
* @description Slave Thread 
*/ 
public class action implements Runnable { 

    private String event = ""; 
    private AtomicInteger state; 

    /** 
    * The constructor (this represents the current instance of a thread). 
    * 
    * @param event 
    * @param state 
    */ 
    public action(String event, AtomicInteger state) { 
     this.event = event; // update this instance of event 
     this.state = state; // update this instance of state 
    } // constructor 

    /** 
    * This method will be called after YourThreadName.Start(); 
    */ 
    @Override 
    public void run() { 
     if (this.event == "resume") { 
      this.OnResume(); // call resume 
     } else { 
      this.OnPause(); // call pause 
     } 
    } // close Runnable run() method 

    /** 
    * The resume function Use the auto lock from synchronized 
    */ 
    public synchronized void OnResume() { 
     System.out.println("[OnResume] The state was.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
     this.setAtomicState(2); // change the state 
     System.out.println("[OnResume] The state is.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
    } // close function 

    /** 
    * The pause function Use the auto lock from synchronized 
    */ 
    public synchronized void OnPause() { 
     System.out.println("[OnPause] The state was.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
     this.setAtomicState(1); // change the state 
     System.out.println("[OnPause] The state is.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
    } // close function 

    /** 
    * Get the atomic integer from memory 
    * 
    * @return Integer 
    */ 
    private Integer getAtomicState() { 
     return state.intValue(); 
    }// close function 

    /** 
    * Update or Create a new atomic integer 
    * 
    * @param value 
    */ 
    private void setAtomicState(Integer value) { 
     if (this.state == null) { 
      state = new AtomicInteger(value); 
     } else 
      state.set(value); 
    } // close function 

} // close the class 

控制檯輸出

[OnResume] The state was..0 // Thread: 9 
[OnResume] The state is..2 // Thread: 9 
[OnPause] The state was..2 // Thread: 10 
[OnPause] The state is..1 // Thread: 10 

正如你所看到的,AtomicInteger state被在內存共享我們的線程rp之間。


解決方案和事情,尋找...

你必須注意的時候做的併發Race Conditions/Deadlocks/Livelocks的唯一的事情。一些RaceConditions發生是因爲Threads是以隨機順序創建的(並且大多數程序員認爲順序排列的思維集合)。

我也行Thread.sleep(1000);讓我Main Thread給出了從線程r一點時間來更新state(允許p運行之前),由於線程的隨機順序。

1)保留對線程的引用並將值傳遞給方法。 信貸(SJuan76,2012)

在我已經發布瞭解決方案,我讓我的Main Thread(又名class start)作爲我的主要傳播者,以跟蹤Atomic Integer爲我的奴隸使用(又名class action)。我的主線也是updating 我的奴隸(內存緩衝區的更新發生在應用程序的後臺,由AtomicInteger類處理)

+0

謝謝。那麼,我必須在線程類中使用AtomicInteger構造函數或方法來獲取更新的狀態嗎?對不起,如果這是不正確的。 Java對我來說很新。 – zkello 2012-07-22 00:17:45

+0

你必須在每個類中使用AtomicInteger聲明(比如說我有一個類'foo',它創建一個帶'boo'類的線程)我需要在這兩個類中聲明的AtomicInteger x'爲了共享它跨越記憶。 – Killrawr 2012-07-22 01:45:53

+0

還要在'onPause()'和'onResume()'中加入'synchronized',例如'protected synchronized void onResume()'。這使得自動鎖定線程或變量'狀態'。並且將避免可能的「種族條件」。問候 – Killrawr 2012-07-22 01:48:34

3

1)保留對線程的引用並將值傳遞給方法。

2)在線程創建期間,傳遞一個與Activity共享的對象。將值傳遞給對象,讓線程定期檢查,直到找到值。

+0

不會第一個解決方案造成可能的競爭條件?如果「onResume」或「onPause」互相依賴? – Killrawr 2012-07-22 00:09:41

1

我使用的參考類,我把它命名爲Share Class。它有與volatile類型的變量。

揮發性用於表示變量的值將被不同線程修改 。

public class Share { 
    public static volatile type M_shared; 
} 

改變這個變量,你應該將其鎖定,並改變值後,解除鎖定。您可以使用Share.M_shared進行讀寫。