2012-07-21 45 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进行读写。