走进Android线程世界

  • 线程与进程
  • 线程的几种创建方式
  • 线程的优先级
  • 线程的几种状态与常用方法
  • 线程间消息通讯
  • 线程安全

1.thread_introduction_png

线程与进程

  • 一个进程至少一个线程
  • 进程可以包含多个线程
  • 进程在执行过程中拥有独立的内存空间,而线程运行在进程内

线程的几种创建方式

  • new Thread:可复写Thread#run方法。也可传递Runnable对象,更加灵活。
  • 缺点:缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom
//传递Runnable对象
1.new Thread(new Runnable(){
  .....
}).start()

//复写Thread#run方法
2.class MyThread extends Thread{
  public void run(){
    ....
  }
}
new MyThread().start()


  • AysncTask,轻量级的异步任务工具类,提供任务执行的进度回调给UI线程
  • 场景:需要知晓任务执行的进度,多个任务串行执行
  • 缺点:生命周期和宿主的生命周期不同步,有可能发生内存泄漏,默认情况所有任务串行执行
class MyAsyncTask extends AsyncTask<String, Integer, String> {
            private static final String TAG = "MyAsyncTask";
            @Override
            protected String doInBackground(String... params) {
                for (int i = 0; i < 10; i++) {
                    publishProgress(i * 10);
                }
                return params[0];
            }
            @Override
            protected void onPostExecute(String result) {
                Log.e(TAG, "result: " + result);
            }
            @Override
            protected void onProgressUpdate(Integer... values) {
                Log.e(TAG, "onProgressUpdate: " + values[0].intValue());
            }
        }
// #1 子类复写方法
AsyncTask asyncTask = new MyAsyncTask();
//AsyncTask所有任务默认串行执行
asyncTask.execute("execute MyAsyncTask");
   or
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"execute MyAsyncTask")

// #2 使用#execute方法,同样串行执行
AsyncTask.execute(new Runnable() {
          @Override
          public void run() {
           ...... 
       }
  });

// #3 使用内置THREAD_POOL_EXECUTOR线程池 并发执行
 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {

            }
        });


  • HandlerThread,适用于主线程需要和工作线程通信,适用于持续性任务,比如轮训的场景,所有任务串行执行
  • 缺点:不会像普通线程一样主动销毁资源,会一直运行着,所以可能会造成内存泄漏

HandlerThread thread = new HandlerThread("concurrent-thread");
thread.start();
ThreadHandler handler = new ThreadHandler(thread.getLooper()) {
      @Override
      public void handleMessage(@NonNull Message msg) {
                switch (msg.what) {
                    case MSG_WHAT_FLAG_1:
                        break;
                }
            }
        };
handler.sendEmptyMessage(MSG_WHAT_FLAG_1);
thread.quitSafely();

//定义成静态,防止内存泄漏
static class ThreadHandler extends Handler{
  public ThreadHandler(Looper looper){
    super(looper)
  }
}


  • IntentService,适用于我们的任务需要跨页面读取任务执行的进度,结果。比如后台上传图片,批量操作数据库等。任务执行完成功后,就会自我结束,所以不需要手动stopservice,这是他跟service的区分
class MyIntentService extends IntentService{
 @Override
 protected void onHandleIntent(@Nullable Intent intent) {  
   int command = intent.getInt("command") 
   ......                                                       }
}
context.startService(new Intent())


  • ✨ThreadPoolExecutor:适用快速处理大量耗时较短的任务场景
 Executors.newCachedThreadPool();//线程可复用线程池
 Executors.newFixedThreadPool();//固定线程数量的线程池
 Executors.newScheduledThreadPool();//可指定定时任务的线程池
 Executors.newSingleThreadExecutor();//线程数量为1的线程池

线程的优先级

public static void main(String[] args){
   Thread thread = new Thread();
   thread.start();
   int ui_proi = Process.getThreadPriority(0)
   int th_proi = thread.getPriority();

   //输出结果
   ui_proi =5
   th_proi=5 
}
  • 线程的优先级具有继承性,在某线程中创建的线程会继承此线程的优先级。那么我们在UI线程中创建了线程,则线程优先级是和UI线程优先级一样,平等的和UI线程抢占CPU时间片资源。

  • JDK Api,限制了新设置的线程的优先级必须为[1~10],优先级priority的值越高,获取CPU时间片的概率越高。UI线程优先级为5

java.lang.Thread.setPriority(int newPriority)
  • Android Api, 可以为线程设置更加精细的优先级(-20~19).优先级priority的值越低,获取CPU时间片的概率越高。UI线程优先级为-10
android.os.Process.setThreadPriority(int newPriority)

线程的几种状态与常用方法

方法名 说明
NEW 初始状态,线程被新建,还没调用start方法
RUNNABLE 运行状态,把"运行中"和"就绪"统称为运行状态
BLOCKED 阻塞状态,表示线程阻塞于锁
WAITING 等待状态,需要其他线程通知唤醒
TIME_WAITING 超时等待状态,表示可以在指定的时间超时后自行返回
TERMINATED 终止状态,表示当前线程已经执行完毕

thread_status

方法名 说明
wait 进入等待池,释放资源对象锁,可使用notify,notifyAll,或等待超时来唤醒
join 等待目标线程执行完后在执行此线程
yield 暂停当前正在执行的线程对象,不会释放资源锁,使同优先级或更高优先级的线程有执行的机会
sleep 使调用线程进入休眠状态,但在一个synchronized块中执行sleep,线程虽然会休眠,但不会释放资源对象锁

线程间消息通讯

  • 主线程向子线程发送消息
class LooperThread extends Thread {
            private Looper looper;

            public Looper getLooper() {
                synchronized (this){
                    if (looper == null && isAlive()) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                return looper;
            }

            @Override
            public void run() {
                Looper.prepare();
                synchronized (this) {
                    looper = Looper.myLooper();
                    notifyAll();
                }
                Looper.loop();
            }

            public void quit() {
                looper.quit();
            }
        }
LooperThread looperThread = new LooperThread();
looperThread.start();
Handler handler = new Handler(looperThread.getLooper()) {
       @Override
       public void handleMessage(@NonNull Message msg) {
       Log.e(TAG, "handleMessage: " + msg.what);
            }
        };
handler.sendEmptyMessage(MSG_WHAT_FLAG_1);

results matching ""

    No results matching ""