2017-05-29 30 views
0

我创建了两个线程在主要活动中操纵共享领域的成员,但价值似乎不是线程更新,因为变量的值是一样的,实际上是即时通讯练同步,这里是我的代码:安卓:线程不更新值

public class ActMain extends Activity { 

Handler handler; 
Integer THREAD_COUNTER = 10; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_act_main); 

    Message m = new Message(); 
    Bundle b = new Bundle(); 
    b.putInt("what", 5); 
    m.setData(b); 


    Thread t1 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      for(int i =0; i < 10; i++){ 
       add(); 
      } 

     } 
    }); 

    Thread t2 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      for(int i = 0; i < 30; i++){ 
       subtract(); 
      } 

     } 
    }); 

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

    Log.i("MainActivity " , " thread counter" + THREAD_COUNTER); 
    //same value 10 of THREAD_COUNTER 

回答

1

我在主要活动中创建了两个线程来操作共享字段成员,但值似乎没有被线程更新......

有几个与你的代码的问题。首先,您启动2个线程,然后立即记录结果。在执行Log.i(...)行时,线程可能实际上并未开始运行。等待后台线程完成,你需要使用join()

t1.start(); 
t2.start(); 
// t1 and t2 start running in the background but we need to wait for them to finish 
t1.join(); 
t2.join(); 
Log.i(...); 

另一个问题是,你不能只是从2个线程加减在THREAD_COUNTER整数。线程从本地缓存内存中获取性能,以便随时线程共享信息,您需要担心锁定和内存同步,以便他们可以协调更新。

随着在多线程环境整数,爪哇给我们的AtomicInteger class这是线程同时更新一个整数值的好方法。所以,你的代码应该是这样的:

// initialize our shared counter to 10 
final AtomicInteger threadCounter = new AtomicInteger(10); 
// ... 
// to add: 
threadCounter.addAndGet(5); 
// to subtract: 
threadCounter.addAndGet(-7); 
// ... 
// to get the value after the joins 
threadCounter.get(); 

情侣其他意见:

  • 全部大写的字段是常数。 threadCounter而不是THREAD_COUNTER
  • 始终使用int,而不是Integer除非值可以是null
  • 不知道如果你这样做,但never call synchronized on a value that can change like an Integer or Boolean。你必须在一个常量对象实例上进行同步,添加一些东西到Integer更改对象,以便多个线程将锁定在不同的对象上。在private final字段上始终呼叫​​是一种很好的模式。
+0

这意味着我们可以指示其他线程等待,直到第一个线程完成加入,然后开始执行,同时我们还强制日志只显示第二个线程完成时,我们做t2.join();我们是否暂停主线程? – blackHawk

+0

也首先我做了t1.join,然后log1然后t2.join然后log2,有时我得到正确的执行t1-> log1-> t2-> log2有时t1-> t2-> log1-> log2,为什么它发生,有时也有t2-> t1-> log1-> log2 – blackHawk

+0

因为线程是同步的。即使您先运行t1.join(),t2也可以完成_before_ t1。您希望通过线程操作获得的控制越多,就越像是线程化程序。您不必担心哪个线程先运行或先完成。 @黑鹰 – Gray

0

基本上当你做那些三线

t1.start(); 
t2.start(); 
Log.i("MainActivity " , " thread counter" + THREAD_COUNTER); 

它们都发生在同一时间,所以当Log.i发生你的线程计数器不更新,你可以使用的AsyncTask,并在打印结束的线程,或做 个log.i在线程本身,

当您打印这样你只需打印线程更新变种之前。

更多关于多线程在Java(学习):

http://beginnersbook.com/2013/03/multithreading-in-java/

为更多的AsyncTask(Android的线程有生命周期,所以你可以做的事情在UI一旦它已经结束了):

https://developer.android.com/reference/android/os/AsyncTask.html