线程其实是Android开发的一个重要模块,我相信大家可能平时用到多选线程情况并不多或者都用的是别人的第三方框架,当然都说了这是一个非常重要的模块所以大家还是需要掌握的毕竟面试也会被考的,我在Android开发 面试题2021年干货汇总解答(一)和Android开发 面试题2021年干货汇总解答(二)中都提到过线程相关的考点,今天我们来看看谷歌为我们提供了哪些实现线程类。
HandlerThread 类
我之前在Android开发 面试题2021年干货汇总解答(一)的线程栏目中提到过谷歌推荐我们使用Handle消息机制实现主线程和子线程相互切换,所以谷歌就为我们提供了HandlerThread线程类,先看一下源码吧:
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
/**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason isAlive() returns false, this method will return null. If this thread
* has been started, this method will block until the looper has been initialized.
* @return The looper.
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/**
* @return a shared {@link Handler} associated with this thread
* @hide
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
/**
* Quits the handler thread's looper.
* <p>
* Causes the handler thread's looper to terminate without processing any
* more messages in the message queue.
* </p><p>
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
* </p><p class="note">
* Using this method may be unsafe because some messages may not be delivered
* before the looper terminates. Consider using {@link #quitSafely} instead to ensure
* that all pending work is completed in an orderly manner.
* </p>
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
*
* @see #quitSafely
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
/**
* Quits the handler thread's looper safely.
* <p>
* Causes the handler thread's looper to terminate as soon as all remaining messages
* in the message queue that are already due to be delivered have been handled.
* Pending delayed messages with due times in the future will not be delivered.
* </p><p>
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
* </p><p>
* If the thread has not been started or has finished (that is if
* {@link #getLooper} returns null), then false is returned.
* Otherwise the looper is asked to quit and true is returned.
* </p>
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
/**
* Returns the identifier of this thread. See Process.myTid().
*/
public int getThreadId() {
return mTid;
}
}
大家可以看到其实代码并不多,主要看一下线程的run方法,这里面主要创建了Looper机制,并且为线程设置了优先级,这样一来我们只需要创建该线程(注意CPU 只能并行处理少量线程,所以如果需要考虑业务优先级可以设置线程优先级),然后创建子线程和主线程Handler就可以手动控制主线程和子线程业务了,简单的先看一下两个Handler实现代码:
//主线程Handler
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
}
};
HandlerThread handlerThread = new HandlerThread("xxx");
handlerThread.start();
Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());
childHandler.sendMessage(msg);
//子线程Handler
class ChildCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
//在子线程中处理业务,然后通过该主线程Handler切回主线程
...
mHandler.sendMessage(msg);
return false;
}
}
是不是很简单非常方便,手动可控发送消息随发随工作十分灵活;
AsyncTask 类
当然在Android开发 面试题2021年干货汇总解答(二)中也提到了AsyncTask并且做了详细解析这里就不过的解析了,就直接看实现代码吧:
private class MyAsyncTask extends AsyncTask<Params, Progress, Result> {
@Override
protected Result doInBackground(Params... params) {
return null;
}
@Override
protected void onProgressUpdate(Progress... values) {
}
@Override
protected void onPostExecute(Result result) {
}
}
new MyAsyncTask().execute(Param1, Param2, Param3);
可以看出AsyncTask并没有HandlerThread那么灵活这种方式主要也就是处理简单的不需要子进程和主进程频繁切换的异步方式。
ThreadPoolExecutor 类
无论是HandlerThread和AsyncTask都只是适合少量线程使用,如果需要大量的线程处理工作责需要使用ThreadPoolExecutor类,该类会创建或销毁更多线程以适应工作负载。
该类我在Android开发 面试题2021年干货汇总解答(一)的多线程中讲的很详细了就不多讲了,顺便提一下支持了哪些线程池:
NewCachedThreadPool:适合大量且耗时短任务;无效扩大的缓存线程池,空闲线程可缓存60s后就会被杀死回收,只要有请求就必须要找到一条工作线程来处理,如果当前没有空闲线程就会重新创建一个新的线程。
NewFixedThreadPool:适合固定数量且耗时较长任务;固定大小线程池,核心线程数和最大线程数都为用户设定线程数,超出固定线程为空闲线程时立即回收,超出固定线程为任务线程时则存放到阻塞队列中等待线程是否后按顺序执行。
NewSingleThreadPool:适合按顺序执行任务,跟NewFixedThreadPool类似不同的就是固定线程数只有一条工作线程,超出任务线程数固定线程数责放到阻塞队列排队输出执行。
NewScheduleThreadPool:适合周期循环执行任务,可设置循环固定线程数、首次延迟时间、循环时间。
欢迎关注微信公众号!你的每个赞和在看,都是对我的支持!👍