day3 线程

2017-09-09  本文已影响5人  WangGavin

线程基础知识

线程状态

线程状态

线程可以有如下6中状态

新创建线程

比如new Thread(r),该线程还没有开始运行,意味着它的状态为new。

可运行线程

一旦调用start方法,线程处于runable状态,一个可运行的线程可能正在运行也可能没有运行,这取决与操作系统给线程提供运行的时间。一旦一个线程开始运行,它不必始终都在运行,事实上,运行过程中,它可能会被中断,而中断的目的就是让其他线程获得运行机会,线程调度的细节依赖于操作系统提供的服务。抢占式调度系统给每一个可运行线程一个时间片来执行任务,当时间片用完,操作系统剥夺该线程的运行权,并给另一个线程运行机会。

被阻塞线程和等待线程

当线程被阻塞或等待线程时,它暂时不活动。它不运行任何代码且消耗最少的资源,知道线程调度器激活它。细节取决于它是怎样达到非活动状态的。

被终止的线程

线程因如下两个原因之一而被终止:

  • 因为run方法正常退出而死亡
  • 因为一个没有捕获的异常终止了run方法而意外死亡

可以调用线程的stop方法杀死线程,该方法抛出一个ThreadDeath错误对象,由此杀死对象,但是,stop方法已经过时,不要再自己的代码中调用这个方法。

线程属性

包括:线程优先级,守护线程,线程组以及处理未捕获异常的处理器

线程优先级

每一个线程有一个优先级。默认情况下,一个线程继承它的父线程的优先级。可以用setPriority方法提高或降低任何一个线程的优先级,范围是MIN_PRIORITY(1)与MAX_PRIORITY(10)之间的任何值。NORM_PRIORITY被定义为5.
每当线程调度器有机会选择新线程时,它首先会选择具有较高优先级的线程。

守护线程

可以通过t.setDaemon(true)将线程转换为守护线程,守护线程的唯一用途是为其它线程提供服务。计时线程就是一个例子,它定时地发送“计时器滴答”信号给其它线程或清空过时的高速缓存项的线程。当只剩下守护线程时,虚拟机就退出了,由于如果只剩下守护线程,就没必要继续运行程序了。

未捕获异常处理器

线程的run方法不能抛出任何被检测的异常,但是,不被检测的异常会导致线程终止,在这种情况下,线程就死亡了。
不需要任何catch字句就可以来处理可被传播的异常,相反,就在线程死亡之前,异常被传递到一个用于未捕获异常的处理器,该处理器必须属于一个实现Thread.UncaughtExceptionHandler接口的类,这个接口只要一个方法:void uncaughtException(Thread t,Throwable e),可以用setUncaughtExceptionHandler为任何线程安装一个处理器,也可以用Thread类的setDefaultUncaughtExceptionHandler()为所有线程安装一个默认的处理器。
如果不安装默认的处理器,默认的处理器为空

同步

在大多数多线程应用中,两个或两个以上的线程需要共享对同一数据的存取。根据各线程访问数据的次序,可能会产生讹误的对象,这种情况成为竞争条件。如果并发的每个线程对共享数据的操作源于块不是原子操作,即它实际上编译后是多个虚拟机指令,比如说增值命令是由几条指令组成的,那么执行它们的线程可以在任何一条指令点上被中断。

锁对象

有两种机制防止代码块并发访问的干扰。

myLock.lock();//a ReentrantLock object
try{
  critical section
}
finally{
    myLock.unlock();//make sure the lock is unlocked even if an exception is thrown
 }

这一结构确保任何时刻只有一个线程进入临界区,一旦一个线程封锁了对象,其它任何线程都无法通过lock语言。当其它线程调用lock时,他们被阻塞,知道第一个线程释放锁对象。

android 的消息机制

android的消息机制主要是指handler的运行机制,handler的运行需要底层的MessageQueue和Looper的支撑。MessageQueue是消息队列,内部储存了一组消息,以队列的形式对外提供插入和删除的工作,MessageQueue只是个消息的存储单元,它不能去处理消息,而Looper就可以以无限循环的形式去查找是否有新消息,如果有的话就处理,没有的话就一直等待着。Handler创建的时候会采用当前线程的Looper来构造消息循环系统。
具体介绍,这儿有一篇很好的文章,http://www.jianshu.com/p/d88e1af5100f

什么姿势开线程?

new thread()

new Thread(new Runnable() {
            @Override
            public void run() {

            }
        }).start();

优点:这种方式简单粗暴,是Android系统中开线程最简单的方式,也只能应用于最简单的场景,简单却伴随着不少的隐患。
缺点

ThreadPoolExecutor 线程池

优点:

AsyncTask

public class MyAsyncTask extends AsyncTask {

       @Override
       protected Object doInBackground(Object[] params) {
           return null;
       }

       @Override
       protected void onPreExecute() {
           super.onPreExecute();
       }

       @Override
       protected void onPostExecute(Object o) {
           super.onPostExecute(o);
       }
   }

优点:

HandlerThread

HandlerThread将Handler,Thread,Looper,MessageQueue几个概念相结合。Handler是线程对外的接口,所有新的message或者runnable都通过handler post到工作线程。Looper在MessageQueue取到新的任务就切换到工作线程去执行。不同的post方法可以让我们对任务做精细的控制,什么时候执行,执行的顺序都可以控制。HandlerThread最大的优势在于引入MessageQueue概念,可以进行多任务队列管理。

特点:

IntentService

它相当于是Service和HandlerThread的结合体,就是在Service里面开了个线程,只是在所有的Message处理完毕之后,工作线程会自动结束,然后Service也会销毁。

Rxjava

观察者与被观察者模式,两个角色可以在不同的线程执行。

上一篇下一篇

猜你喜欢

热点阅读