zoukankan      html  css  js  c++  java
  • android 避免线程的重复创建(HandlerThread、线程池)

    最近在android开发中,用到都是new Thread(){...}.start()这种方式。本来这样是可以,但是最近突然爆出Performing stop of activity that is not resumed 错误,google了一下发现是线程多次创建的问题;

    多次使用上面的方式,会创建多个匿名线程。使得程序运行起来越来越慢。

    因此,可以考虑使用一个Handler来启动一个线程,当该线程不再使用就删除,保证线程不会重复创建。
    一般会使用Handler handler = new Handler(){...}创建Handler。这样创建的handler是在主线程即UI线程下的Handler,
    即这个Handler是与UI线程下的默认Looper绑定的。Looper是用于实现消息队列和消息循环机制的。
    因此,如果是默认创建Handler那么如果线程是做一些耗时操作如网络获取数据等操作,这样创建Handler是不行的。
    Android API提供了HandlerThread来创建线程。官网的解释是:Handy class for starting a new thread that has a looper.
    The looper can then be used to create handler classes. Note that start() must still be called.
    HandlerThread实际上就一个Thread,只不过它比普通的Thread多了一个Looper。
    创建HandlerThread时要把它启动了,即调用start()方法。然后创建Handler时将HandlerThread中的looper对象传入。

    代码如下

    HandlerThread thread = new HandlerThread("MyHandlerThread");  
    thread.start();  
    mHandler = new Handler(thread.getLooper());  
    mHandler.post(new Runnable(){...});  
     

    完整代码(需要在调用线程的Activity 在销毁时 移除线程)

     1 public class MainActivity extends Activity implements OnClickListener{  
     2 private Handler mHandler;  
     3 private HandlerThread mHandlerThread;  
     4 private boolean mRunning;  
     5 private Button btn;  
     6 @Override  
     7 protected void onDestroy() {  
     8     mRunning = false;  
     9     mHandler.removeCallbacks(mRunnable);  
    10     super.onDestroy();  
    11 }  
    12 @Override  
    13 protected void onResume() {  
    14     mRunning = true;  
    15     super.onResume();  
    16 }  
    17 @Override  
    18 protected void onStop() {  
    19     mRunning = false;  
    20     super.onStop();  
    21 }  
    22 @Override  
    23 protected void onCreate(Bundle savedInstanceState) {  
    24     super.onCreate(savedInstanceState);  
    25     setContentView(R.layout.activity_main);  
    26     btn = (Button) findViewById(R.id.btn);  
    27     btn.setOnClickListener(this);  
    28     mHandlerThread = new HandlerThread("Test", 5);  
    29     mHandlerThread.start();  
    30     mHandler = new Handler(mHandlerThread.getLooper());  
    31 }  
    32 private Runnable mRunnable = new Runnable() {  
    33     @Override  
    34     public void run() {  
    35         while (mRunning) {  
    36             Log.d("MainActivity", "test HandlerThread...");  
    37             try {  
    38                 Thread.sleep(200);  
    39             } catch (Exception e) {  
    40                 e.printStackTrace();  
    41             }  
    42         }  
    43     }  
    44 };  
    45 @Override  
    46 public void onClick(View v) {  
    47     switch(v.getId()) {  
    48     case R.id.btn :  
    49         mHandler.post(mRunnable);  
    50         break;  
    51     default :  
    52         break;  
    53     }  
    54 }  
    55 }  

     转自:http://blog.csdn.net/a_tao123/article/details/41279019

    /***************************************************************************************************************************************************************************/

    然而最后我发现还是线程池更好用。。。

    ExecutorService mExecutorService;
    mExecutorService.submit(new Runnable() {
                @Override
                public void run() {
                    //需要操作的代码
                }
            });

    将每次需要提交的线程都用mExecutorService.submit()放入线程池中即可。

  • 相关阅读:
    如何进入高效学习状态
    shell printf命令:格式化输出语句
    C# virtual、abstract
    git解决Could not execute editor
    go defer笔记
    git从其他分支提取文件merge到当前分支
    golang map
    状态模式
    golang单例模式
    go 单元测试时读取配置文件
  • 原文地址:https://www.cnblogs.com/Sharley/p/6934121.html
Copyright © 2011-2022 走看看