异步处理的深入研究 一

Thread

Executor

HandlerThread

AsyncTask

Service

IntentService

AsyncQueryHandler

Loader


Thread

public class Thread implements Runnable

public interface Runnable {
    public void run();
}


上面的代码表示Thread类实现了Runnable接口。什么叫启一个线程?这是理解通过Thread解决异步问题的关键,我们使用时不会主动调用run方法,而Thread类里也没有显式调用run方法,总有地方在调用它吧否则里面的代码怎么执行,那就是JVM调用的,至于哪儿调用的怎么调用的何时调用的我们不管,理解是关键。反过来,为什么不这样写:

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

以前从未这样想过写过,一时还觉得这样写没啥不对。run里面执行的是耗时操作,这样直接调用不就和随便定义一个类调用一个方法来执行一样了么,怎么解决异步问题。所以从定义Thread的角度来讲,如果我要写一个Thread类,首先需要新起一个线程,然后接受耗时操作的内容,具体要干什么Thread是决定不了的,那么run方法就是来接受Thread类外定义的耗时操作内容;而start方法呢?


public synchronized void start() {
        checkNotStarted();

        hasBeenStarted = true;

        nativeCreate(this, stackSize, daemon);
    }

private native static void nativeCreate(Thread t, long stackSize, boolean daemon);

start方法顾名思义就是让类外部来决定何时让该线程运行。那么,知道了上面的内容,就不难理解Thread的构造允许传入Runnable对象了,实际一个意思。在后面所有的异步解决所用到的类或方法都离不开Thread,因为创建新线程只能依靠它。而它的缺陷很简单,无法停止,也就是说,只要启动后,除非执行完毕或报错都停不了,其stop方法也早已被废弃,原因也很好理解,锁。

那么一般的解决办法都是绕行,要么抛错要么不管。抛错的方式需要了解线程的几种状态以及violate,原理都是一样通过报错的方式来停止线程执行;不管的方式却是一个暧昧的解决办法,后面会讲到的线程池的最大贡献就是对多个线程进行管理,可以reject以及设置最多线程数等等,为什么要管理要重用线程,原因就是害怕线程过多导致性能问题,而线程无法停止最致命的后果就是相对时间内不能停止的线程数量过多导致的性能问题,而以不管的思路来解决怎么理解,其实就像车库一样,只有10个车位,进来的10辆车我不管也管不了你什么时候离开,但我可以阻止后面的车进来。也就是说程序里起一个线程跑死循环电脑不会卡死,还可以做其他事,如果有一万个死循环线程那就悲剧了。那么在实际的项目中,比如一个网络请求迟迟没有响应就是利用的超时抛错来停止线程的,为什么不用不管的方式来解决呢,试想跳到一个页面发现连接池满了,当前页面的请求根本不执行,这该怎么给用户反馈呢?那么一般情况就是采用超时报错加线程池的方式来做,车库一辆车只能停一天,车库满了就在门口排队等,第二天队列里的前十辆车肯定可以停进去。

说了这么多,android开发中对直接使用Thread还是比较谨慎的,因为用户体验的需求是各种各样的,而实现这些需求所用到的策略还是需要去理解其原理,为何它会出现,为何以这种方式出现等等逗比的问题往往会让我们理解得跟深。


你可能感兴趣的:(异步处理的深入研究 一)