Android线程与线程池

引言

在Android中,几乎完全采用了Java中的线程机制。线程是最小的调度单位,在很多情况下为了使APP更加流程地运行,我们不可能将很多事情都放在主线程上执行,这样会造成严重卡顿(ANR),那么这些事情应该交给子线程去做,但对于一个系统而言,创建、销毁、调度线程的过程是需要开销的,所以我们并不能无限量地开启线程,那么对线程的了解就变得尤为重要了。


Thread/Runnable/Callable

一般实现线程的方法有两种,一种是类继承Thread,一种是实现接口Runnable。这两种方式的优缺点如何呢?我们知道Java是单继承但可以调用多个接口,所以看起来Runnable更加好一些。

继承Thread

class MyThread extend Thread(){
    @Override
    public void run() {
        super.run();
        Log.i(Thread.currentThread().getId());
    }
}
new MyThread().start();

实现Runnable接口

class MyThread implements Runnable{
   
    @Override
    public void run() {
        Log.i("MyThread", Thread.currentThread().getName());
    }
}
MyThreaed myThread = new MyThread();
new Thread(myThread).start();

当我们调用Thread时,会有两种方式:

Thread myThread = new Thread();
myThread.run();
myThread.start();

我们应该知道,run()方法只是调用了Thread实例的run()方法而已,它仍然运行在主线程上,而start()方法会开辟一个新的线程,在新的线程上调用run()方法,此时它运行在新的线程上。

Runnable只是一个接口,所以单看这个接口它和线程毫无瓜葛,可能一部分人会以为Runnable实现了线程,这种理解是不对的。Thread调用了Runnable接口中的方法用来在线程中执行任务。

public interface Runnable {
    public void run();
}

public interface Callable<V> {
    V call() throws Exception;
}

Runnable 和 Callable 都代表那些要在不同的线程中执行的任务。Runnable 从 JDK1.0 开始就有了,Callable 是在 JDK1.5 增加的。它们的主要区别是 Callable 的 call() 方法可以返回值和抛出异常,而 Runnable 的 run() 方法没有这些功能。Callable 可以返回装载有计算结果的 Future 对象。

我们通过对比两个接口得到这样的结论:

  • Callable 接口下的方法是 call(),Runnable 接口的方法是 run();
  • Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值的;
  • call() 方法可以抛出异常,run()方法不可以的;
  • 运行 Callable 任务可以拿到一个 Future 对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过 Future 对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果;

然而…Thread类只支持Runnable接口,由此引入FutureTask的概念。


FutureTask

FutureTask 实现了 Runnable 和 Future,所以兼顾两者优点,既可以在 Thread 中使用,又可以在 ExecutorService 中使用。

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

使用 FutureTask 的好处是 FutureTask 是为了弥补 Thread 的不足而设计的,它可以让程序员准确地知道线程什么时候执行完成并获得到线程执行完成后返回的结果。FutureTask 是一种可以取消的异步的计算任务,它的计算是通过 Callable 实现的,它等价于可以携带结果的 Runnable,并且有三个状态:等待、运行和完成。完成包括所有计算以任意的方式结束,包括正常结束、取消和异常。

除了以上这些,在Android中充当线程的角色还有AsyncTask、HandlerThread、IntentService。它们本质上都是由Handler+Thread来构成的,不过不同的设计让它们可以在不同的场合发挥更好的作用。我们来简单地说一下它们各自的特点:

AsyncTask,它封装了线程池和Handler,主要为我们在子线程中更新UI提供便利。
HandlerThread,它是个具有消息队列的线程,可以方便我们在子线程中处理不同的事务。
IntentService,我们可以将它看做为HandlerThread的升级版,它是服务,优先级更高。

下面我来通过源码,用法等来认清这些线程。


AsyncTask

AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和结果传递给主线程并且在主线程中更新UI。

1. 用法

AsyncTask是一个抽象泛型类,声明:public abstract class AsyncTask<Params, Progress, Result>;
并且提供了4个核心方法。

  • 参数1,Params,异步任务的入参;
  • 参数2,Progress,执行任务的进度;
  • 参数3,Result,后台任务执行的结果;
  • 方法1, onPreExecute(),在主线程中执行,任务开启前的准备工作;
  • 方法2,doInbackground(Params…params),开启子线程执行后台任务;
  • 方法3,onProgressUpdate(Progress values),在
  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值