移动架构--14.线程、异步知识

一、介绍生产者消费者模式(移动架构--9.生产者消费者模式)
二、传统的线程继承自Thread或实现Runnable接口,线程的执行没有返回值,引出FutureTask、Callable、Excutor。Callable在子线程中执行,因为被FutureTask给包装了,FutureTask实现了Runnable接口。FutureTask称为异步任务,返回值通过get方法调用,get是阻塞的,只有当FutureTask的done方法执行完才能拿到。FutureTask的执行是被丢到线程池中的,通过线程池的execute方法执行。

简单的FutureTask,Callable,Excutor例子

public class Client{
  //异步任务的执行
  static class Task implements Callable{
    @Override
    public Integer call() throws Exception {
      int i = 0;
      for (; i < 10; i++) {
        try {
          System.out.println(Thread.currentThread().getName() + "_"+i);
          Thread.sleep(500);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      return i;
    }
  }


  public static void main(String[] args) {
    Task work = new Task();
    FutureTask future = new FutureTask(work){
      @Override
      protected void done() {
        try {
          System.out.println("done:"+get());
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    };
    ExecutorService executor = Executors.newCachedThreadPool();
    executor.execute(future);
  }
}

Callable为异步任务提供了返回值,FutureTask包装了异步任务,丢给线程池去执行。
三、介绍二是为了能看懂AsyncTask的源码
3.1在构造方法中:

mWorker = new WorkerRunnable()
private static abstract class 
WorkerRunnable implements Callable 

mFuture = new FutureTask(mWorker)
protected void done()---->postResultIfNotInvoked(get());

// 主线程的looper
//  public InternalHandler() {
// super(Looper.getMainLooper());
// }

3.2执行execute方法其实是调用线程池执行的

executeOnExecutor(sDefaultExecutor, params)
SerialExecutor implements Executor

因此当有很多异步任务,会造成异常,就是线程池的线程已经达到最大值,并且异步任务队列已经慢的情况下。

Executors.newScheduledThreadPool(25)

异步任务也会造成内存泄漏

class MyTask extends AsyncTask{
  int i = 0;
  @Override
  protected Void doInBackground(Void... params) {
    while(!isCancelled()){//在此判断异步任务是否取消
    }
    return null;
  }     
}
//Activity onDestory的时候
task.cancel(true);

四、HandlerThread
HandlerThred=Handler+Thread;
子线程返回的结果通过Handler发送消息给主线程的Looper增加了主线程的压力,因此HandlerThread内部有自己的looper,减小主线程的压力。
简单使用

HandlerThread handThread = new HandlerThread("this is handthread");
Handler subHandler = new Handler(handThread.getLooper());
//这样通过subHandler发送的消息会交给子线的Looper处理
//在子线程更新UI的方法
//1.runOnUiThread(new Runnable(){@Override void run(){代码}})
//2.Handler hand = new Handler(getMainLooper()).
//  .post(new Runnable(){@Override void run(){代码})

HandThread中主要介绍打开相机,与回调相机采集的数据,一个线程执行两个任务
用AsyncTask实现,其实一个在子线程一个在主线程

class MyTask extends AsyncTask implements PreviewCallback{
//doInBackground子线程
//onPreviewFrame主线程
}
//原因分析
public class Task extends Thread{
@Override
void run(){
System.out.println(Thread.currentThread().getName() + "_run");
}
void dosomething(){
System.out.println(Thread.currentThread().getName() + "_dosomething");
}
}
//调用
Task task = new Task();
task.start();
task.dosomething();

利用HandlerThread可以实现打开相机和回调预览

//1.创建HandlerThread
HandlerThread mHandlerThread = new HandlerThread("my_handlerthread");
//2.具体要做的事情打开相机+回调显示
class MyTask implements Runnable, PreviewCallback{……}
//3.调用实现一个线程两个任务
mHandlerThread.start();
subHandler = new Handler(mHandlerThread.getLooper());
subHandler.post(new MyTask());

特殊性,回调的执行源码,有looper的则用子线程的looper否则用主线程的looper因此在一个子线程中两个任务

五、IntentService
IntentService = Intent+HandlerThread+Service
直接在服务中启动一个HandlerThread,提高了子线程的优先级。

public class MyIntentService extends IntentService {
//至少要有一个空的构造方法
  public MyIntentService() {
    super("MyIntentService");
  }
  public MyIntentService(String name) {
    super(name);
  }
  @Override
  public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    Log.d("jason", Thread.currentThread().getName() + "_onStart");
  }
  //UI线程发送Intent,会在子线程中执行
  @Override
  protected void onHandleIntent(Intent intent) {
    Log.d("jason", Thread.currentThread().getName() +
       "_onHandleIntent");
  }
}
//调用Intent intent = new Intent(this,MyIntentService.class);
//startService(intent);

六Loader保证子线程与Activity生命周期一致(LoaderManager)

//1.执行Loader回调
private MyLoaderCallback mLoaderCallback = new MyLoaderCallback();
getLoaderManager().initLoader(0, null, mLoaderCallback);
//2.实现LoaderCallbacks

private class MyLoaderCallback
implements 
LoaderManager.LoaderCallbacks {
  //创建Loader
  @Override
  public Loader onCreateLoader(int id, Bundle args) {
    //加载的过程在子线程中进行
    CursorLoader loader = new CursorLoader(MainActivity.this, 
    CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION,
    null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
    Log.d(TAG, "onCreateLoader");
    return loader;
  }

  //Loader检测底层数据,当检测到改变时,
  //自动执行新的载入获取最新数据
  //Activity/Fragment所需要做的就是初始化Loader,
  //并且对任何反馈回来的数据进行响应。
  @Override
  public void onLoadFinished(Loader loader, Cursor data) {
    if (data == null)
      return;
    mAdapter.swapCursor(data);
    Log.d(TAG, "onLoadFinished data count = " + data.getCount());
  }
  //OnDestroy,自动停止load
  @Override
  public void onLoaderReset(Loader loader) {
      Log.d(TAG, "onLoaderReset");
      mAdapter.swapCursor(null);
  }
}

你可能感兴趣的:(移动架构--14.线程、异步知识)