2011-03-04 44 views
0

我有一个不断循环和对象上执行操作的线程。这些操作被封装在​​块中。当我尝试从另一个线程(无论是UI还是一个新的线程)获取对象的锁时,我一直等待对象被循环线程释放。Android的线程和对象锁定

我在这里错过了什么?

活动

package com.ThreadTest; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class ThreadTest 
    extends Activity 
    implements OnClickListener 
{ 
    private Looper looper; 


    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     ((Button) findViewById(R.id.btnNewThread)).setOnClickListener(this); 
     ((Button) findViewById(R.id.btnUIThread)).setOnClickListener(this); 

     looper = new Looper(); 
     looper.startThread(); 
    } 


    public void onClick(View view) 
    { 
     if (view.getId() == R.id.btnNewThread) 
     { 
      new Thread() 
      { 
       public void run() 
       { 
        looper.sendRequest(); 
       } 
      }.start(); 
     } 
     else 
     { 
      looper.sendRequest(); 
     } 
    } 


    @Override 
    protected void onPause() 
    { 
     looper.stopThread(); 
     super.onPause(); 
    } 
} 

不断循环螺纹

package com.ThreadTest; 

import android.util.Log; 

public class Looper 
{ 
    private static String TAG = "Looper"; 
    private final byte[] _data = new byte[65536]; 
    private final long sleepTime = 100; 
    private final long sleepTime2 = 150; 

    private LoopingThread _loopingThread; 


    public Looper() 
    { 
    } 


    public void stopThread() 
    { 
     Log.w(TAG, "stopThread"); 
     _loopingThread.shutdown(); 
    } 


    public void startThread() 
    { 
     Log.w(TAG, "startThread"); 
     _loopingThread = new LoopingThread(); 
     _loopingThread.start(); 
    } 


    public final void sendRequest() 
    { 
     final long preSync = System.currentTimeMillis(); 
     Log.w("sendRequest", "WAITING " + 
      Thread.currentThread().getName() + 
      " (" + 
      Thread.currentThread().getPriority() + 
      ")"); 

     synchronized (_data) 
     { 
      Log.e("sendRequest", "GOT LOCK " + (System.currentTimeMillis() - preSync) + "ms"); 

      try 
      { 
       Thread.sleep(sleepTime); //simulate processing 
      } 
      catch (final InterruptedException e) 
      { 
       //Ignore 
      } 
     } 
    } 

    private class LoopingThread 
     extends Thread 
    { 
     private volatile boolean shutdown = false; 


     public LoopingThread() 
     { 
      super("LoopingThread"); 
     } 


     public void run() 
     { 
      long current = System.currentTimeMillis(); 

      while (!shutdown) 
      { 
       Log.i("LoopingThread", Thread.currentThread().getName() + 
        " (" + 
        Thread.currentThread().getPriority() + 
        ")"); 
       synchronized (_data) 
       { 
        try 
        { 
         Thread.sleep(sleepTime);//simulate processing 
        } 
        catch (final Exception e) 
        { 
         //Ignore 
        } 
       } 
       current += 250; 
       do 
       { 
        try 
        { 
         synchronized (_data) 
         { 
          Thread.sleep(sleepTime2);//simulate processing 
         } 
        } 
        catch (final Exception e) 
        { 
         //Ignore 
         return; 
        } 
       } 
       while (!shutdown && current >= System.currentTimeMillis()); //loop for 250 ms 
      } 
     } 


     public void shutdown() 
     { 
      shutdown = true; 

      if (isAlive()) 
      { 
       interrupt(); 

       try 
       { 
        join(); 
       } 
       catch (final InterruptedException e) 
       { 
        // Ignored... 
       } 
      } 
     } 
    } 

} 

样本输出

... 
03-04 16:03:27.675: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:28.056: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:28.355: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:28.717: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:29.040: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:29.400: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:29.721: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:30.034: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:30.125: WARN/sendRequest(18846): WAITING Thread-9 (5) 
03-04 16:03:30.351: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:30.664: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:30.924: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:31.225: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:31.588: INFO/LoopingThread(18846): LoopingThread (5) 
03-04 16:03:31.909: INFO/LoopingThread(18846): LoopingThread (5) 
...(repeats) 

回答

0

sleep被放在精简代码模拟处理。一些挖后,解决办法是把一个Thread.yield()do .. while循环之后,以使弯针线,跳出繁忙的环路足够长的其他线程获取锁的。 Looper线程太快地锁定了对象,并且从未给其他线程提供访问它的机会。

我猜Android的虚拟机是从Sun的虚拟机不同。此代码在Java applet和BlackBerry上执行得很好。但是,由于原始代码显然不是执行手头任务的最佳方式,因此需要对其进行修改。目前Thread.yeild()是一款创可贴解决方案。

0

LoopingThread.run保持锁定对象(_data),因为线程在同步节中处于睡眠模式。

LoopingThread.run应放在睡眠模式的同步(_data)段之外,所以一个又一个线程将有机会获得锁。