Android——线程和线程池

线程和线程池

  • AsyncTask
  • IntentService
  • 线程池
    • ThreadPoolExecutor
    • FixedThreadPool
    • CachedThreadPool
    • ScheduledExecutor
    • SingleThreadExecutor

AsyncTask

使用案例可看Android基础——异步消息处理,需要注意

  • AsyncTask必须在主线程中加载,在ActivityThread的main()中会调用AsyncTask的init()
  • AsyncTask对象必须在主线程中创建及调用execute(),且一个对象只能调用一次
  • 不要直接调用onPreExecute()、onPostExecute()、doInBackground()、onProgressUpdate()
  • execute()串行执行,executeOnexecutor()传入THREAD_POOL_EXECUTOR并行执行

execute()调用executeOnExecutor()传入sDefaultExecutor,将params封装到WorkerRunnable、FutureTask

public final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);
}public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {......mStatus = Status.RUNNING;onPreExecute();mWorker.mParams = params;exec.execute(mFuture);return this;
}

sDefaultExecutor是一个串行线程池,调用其execute()

  • 将上面封装的FutureTask插入到mTasks
  • 如果当前没有正在运行的AsyncTask任务,则调用scheduleNext()
  • scheduleNext()将mTasks中的任务取出,在线程池中执行FutureTask的run()
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();private static class SerialExecutor implements Executor {final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();Runnable mActive;public synchronized void execute(final Runnable r) {mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {scheduleNext();}}});if (mActive == null) {scheduleNext();}}protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {THREAD_POOL_EXECUTOR.execute(mActive);}}
}public static final Executor THREAD_POOL_EXECUTOR;
static {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), sThreadFactory);threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy);THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

FutureTask的run()会调用到WorkerRunnable的call()

  • 调用doInBackground()
  • 然后调用postResult(),通过Handler发送MESSAGE_POST_RESULT,这里的Handler实际是InternalHandler
public AsyncTask() {this((Looper) null);
}public AsyncTask(@Nullable Handler handler) {this(handler != null ? handler.getLooper() : null);
}public AsyncTask(@Nullable Looper callbackLooper) {mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()? getMainHandler(): new Handler(callbackLooper);mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Result result = null;try {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);result = doInBackground(mParams);Binder.flushPendingCommands();} catch (Throwable tr) {mCancelled.set(true);throw tr;} finally {postResult(result);}return result;}};......};
}private Result postResult(Result result) {Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;
}private Handler getHandler() {return mHandler;
}private static Handler getMainHandler() {synchronized (AsyncTask.class) {if (sHandler == null) {sHandler = new InternalHandler(Looper.getMainLooper());}return sHandler;}
}

InternalHandler会回调onProgressUpdate() / onCancelled() / onPostExecute,为了能够让执行环境切换到主线程,InternalHandler必须在主线程中创建

private static class InternalHandler extends Handler {public InternalHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:result.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}
}private void finish(Result result) {if (isCancelled()) {onCancelled(result);} else {onPostExecute(result);}mStatus = Status.FINISHED;
}

IntentService

IntentService继承了Service,且是抽象类,用于执行后台耗时任务,执行完后自动停止

public class LocalIntentService extends IntentService {private static final String TAG = "LocalIntentService";public LocalIntentService() {super(TAG);}@Overrideprotected void onHandleIntent(@Nullable Intent intent) {String action = intent.getStringExtra("action");Log.d(TAG, "onHandleIntent: receive action = " + action);SystemClock.sleep(5000);if ("com.demo.demo0".equals(action)) {Log.d(TAG, "onHandleIntent: handle action = " + action);}}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "onDestroy: ");}
}

如上,在onHandleIntent()中处理intent中传过来的数据,如下通过startService()调用

public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent service = new Intent(this,LocalIntentService.class);service.putExtra("action","com.demo.demo0");startService(service);service.putExtra("action","com.demo.demo1");startService(service);}
}

打印如下

onHandleIntent: receive action = com.demo.demo0
onHandleIntent: handle action = com.demo.demo0
onHandleIntent: receive action = com.demo.demo1
onDestroy: 

下面分析其原理,onCrete()如下,创建HandlerThread,其调用start(),并用其Looper创建一个ServiceHandler

@Override
public void onCreate() {super.onCreate();HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);
}private volatile ServiceHandler mServiceHandler;private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}
}

HandlerThread继承了Thread,start()会调用其run(),内部创建Looper,当无需使用时,需调用quit() / quitSafely()终止Looper来终止线程

@Override
public void run() {mTid = Process.myTid();Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1;
}

启动服务调用onStartCommand()、onStart(),通过mServiceHandler发送Message,handleMessage()会在HandlerThread中执行(会到创建Handler所在的Looper中执行),回调onHandleIntent()处理耗时任务,处理完后调用stopSelf()停止服务

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}@Override
public void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);
}

线程池

  • 重用线程池中的线程,可以避免创建和销毁带来的性能开销
  • 控制最大并发数,避免线程之间抢占资源导致阻塞
  • 对线程进行管理,提供定时执行、循环执行等功能

ThreadPoolExecutor

通过一系列参数配置线程池

  • corePoolSize:核心线程数,当allowsCoreThreadTimeOut=true且核心线程闲置时间超过keepAliveTime就会终止,否则一直存活
  • maximumPoolSize:最大线程数,超过后接下来的任务会被阻塞
  • keepAliveTime:非核心线程闲置时间,超过后非核心线程会被回收,当allowsCoreThreadTimeOut=true同样作用于核心线程
  • unit:指定keepAliveTime的时间单位
  • workQueue:线程池的任务队列,存储execute()提交的Runnable对象
  • threadFactory:线程工厂,为线程池创建新线程
  • handler:当线程池已满或无法成功执行时,调用其中的rejectedExecution()抛出异常
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;
}
  • 当线程数量 < 核心线程数量,启动核心线程执行任务
  • 当线程数量 >= 核心线程数量,任务插入队列等待
  • 当任务队列已满,若未达到最大线程数量,启动非核心线程执行任务,若已达到最大线程数量,则调用rejectedExecution()

FixedThreadPool

只有核心线程且数量固定,闲置时不会被回收(可以更快速响应请求),当线程池的线程都在工作时,新任务处于等待状态直到线程空闲出来

public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}

CachedThreadPool

无核心线程,最大线程数量无限制,闲置60s会被回收,当线程池中的线程都在工作时,会创建新线程处理新任务(任何任务都会被立即执行,适合执行大量耗时少的任务),无任务时不占用系统资源

public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}

ScheduledExecutor

核心线程数量固定,非核心线程数量无限制,闲置10ms后回收,主要用于执行定时任务和具有固定周期的重复任务,schedule()可以延迟运行,scheduleAtFixedRate()可以在延迟后每隔一段时间运行

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize);
}
private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,new DelayedWorkQueue());}

SingleThreadExecutor

只有一个核心线程,确保所有任务都在同一线程中按顺序执行,统一所有任务到一个线程,不需要处理线程同步问题

public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/69594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

装饰器模式简介

概念&#xff1a; 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;允许您在不改变现有对象结构的情况下&#xff0c;动态地将新功能附加到对象上。通过创建一个包装器类来扩展原始类的功能。这个包装器类具有与原始类相同的接口&#x…

对称二叉树(Leetcode 101)

题目 101. 对称二叉树 思路 使用层序遍历&#xff0c;遍历当前层的节点时&#xff0c;如该节点的左&#xff08;右&#xff09;孩子为空&#xff0c;在list中添加null&#xff0c;否则加入左&#xff08;右&#xff09;孩子的值。每遍历完一层则对当前list进行判断&#xff0c…

从零学算法(剑指 Offer 61)

从若干副扑克牌中随机抽 5 张牌&#xff0c;判断是不是一个顺子&#xff0c;即这5张牌是不是连续的。2&#xff5e;10为数字本身&#xff0c;A为1&#xff0c;J为11&#xff0c;Q为12&#xff0c;K为13&#xff0c;而大、小王为 0 &#xff0c;可以看成任意数字。A 不能视为 14…

如何做一个api商品数据接口?

在构建一个API商品数据接口的过程中&#xff0c;我们需要涉及前端开发、后端开发、数据库设计以及API设计等多个方面。以下是一个基本的步骤和代码示例&#xff1a; 第一步&#xff1a;数据库设计 首先&#xff0c;我们需要设计一个数据库来存储商品信息。在这个例子中&#…

Git常用命令用法

参考视频&#xff1a;真的是全能保姆 git、github 保姆级教程入门&#xff0c;工作和协作必备技术&#xff0c;github提交pr - pull request_哔哩哔哩_bilibili 1.Git初始化 首先设置名称和邮箱。然后初始化一下&#xff0c;然后就创建了一个空的Git仓库。 PS D:\golang\oth…

区块链面临六大安全问题 安全测试方案研究迫在眉睫

区块链面临六大安全问题 安全测试方案研究迫在眉睫 近年来&#xff0c;区块链技术逐渐成为热门话题&#xff0c;其应用前景受到各国政府、科研机构和企业公司的高度重视与广泛关注。随着技术的发展&#xff0c;区块链应用与项目层出不穷&#xff0c;但其安全问题不容忽视。近年…

node socket.io

装包&#xff1a; yarn add socket.io node后台&#xff1a; const express require(express) const http require(http) const socket require(socket.io) const { getUserInfoByToken } require(../../utils/light/tools)let app express() const server http.createS…

【C++漂流记】结构体的定义和使用、结构体数组、结构体指针、结构体做函数参数以及结构体中const的使用

结构体&#xff08;struct&#xff09;是C语言中一种重要的数据类型&#xff0c;它由一组不同类型的成员组成。结构体可以用来表示一个复杂的数据结构&#xff0c;比如一个学生的信息、一个员工记录或者一个矩形的尺寸等。 结构体定义后&#xff0c;可以声明结构体变量&#xf…

NCCoE发布“向后量子密码学迁移”项目进展情况说明书

近日&#xff0c;NIST下属的国家网络安全中心&#xff08;NCCoE&#xff09;发布了一份向后量子密码学迁移&#xff08;Migration to Post-Quantum Cryptography&#xff09;项目情况说明书。该文档简要概述了向后量子密码学迁移项目的背景、目标、挑战、好处和工作流程&#x…

【HTML5高级第二篇】WebWorker多线程、EventSource事件推送、History历史操作

文章目录 一、多线程1.1 概述1.2 体会多线程1.3 多线程中数据传递和接收 二、事件推送2.1 概述2.2 onmessage 事件 三、history 一、多线程 1.1 概述 前端JS默认按照单线程去执行&#xff0c;一段时间内只能执行一件事情。举个栗子&#xff1a;比方说古代攻城游戏&#xff0c…

基于LinuxC语言实现的TCP多线程/进程服务器

多进程并发服务器 设计流程 框架一&#xff08;使用信号回收僵尸进程&#xff09; void handler(int sig) {while(waitpid(-1, NULL, WNOHANG) > 0); }int main() {//回收僵尸进程siganl(17, handler);//创建服务器监听套接字 serverserver socket();//给服务器地址信息…

Jenkins自动构建(Gitee)

Gitee简介安装JenkinsCLI https://blog.csdn.net/tongxin_tongmeng/article/details/132632743 安装Gitee jenkins-cli install-plugin gitee:1.2.7 # https://plugins.jenkins.io/gitee/releases获取安装命令(稍作变更) JenkinsURL Dashboard-->配置-->Jenkins Locatio…

ARTS第五周:A - 最大公约数

数字 function gcd(int $x, int $y): int {while($y^$x^$y^$x%$y);return $x; }位运算&#xff1a;异或&#xff1a;gcd(a,b) gcd(b,a mod b) 字符串 <?phpclass Solution {/*** param String $str1* param String $str2* return String*/function gcdOfStrings($str1, …

MySQL 8.0 OCP (1Z0-908) 考点精析-安装与配置考点1:设置系统变量

文章目录 MySQL 8.0 OCP (1Z0-908) 考点精析-安装与配置考点1&#xff1a;设置系统变量系统变量的确认设置系统变量的方法SET命令设置系统变量SET命令语法动态系统变量&#xff08;Dynamic System Variables&#xff09;全局级别变量的设置方法会话级别变量的设置方法系统变量的…

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?

如何使用好 ArkUI 的 Reusable&#xff1f; OpenHarmony 组件复用机制 在ArkUI中&#xff0c;UI显示的内容均为组件&#xff0c;由框架直接提供的称为 系统组件&#xff0c;由开发者定义的称为 自定义组件。 在进行 UI 界面开发时&#xff0c;通常不是简单的将系统组件进行组合…

SpringBoot的测试方案

写完代码后&#xff0c;测试是必不可少的步骤&#xff0c;现在来介绍一下基于SpringBoot的测试方法。 基于SpringBoot框架写完相应功能的Controller之后&#xff0c;然后就可以测试功能是否正常&#xff0c;本博客列举MockMvc和RestTemplate两种方式来测试。 准备代码 实体类…

NIO原理浅析(三)

epoll 首先认识一下epoll的几个基础函数 int s socket(AF_INET, SOCK_STREAM, 0); bind(s, ...); listen(s, ...);int epfd epoll_create(...) epoll_ctl(epfd, ...); //将所有需要监听的socket添加到epfd中while(1) {int n epoll_wait(...);for(接受到数据的socket) {//处…

Kotlin 环境下解决属性初始化问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

react使用hook封装一个tab组件

目录 react使用hook封装一个tab组件Tabbar.jsx使用组件效果 react使用hook封装一个tab组件 Tabbar.jsx import PropsTypes from "prop-types"; import React, { useEffect, useState } from react; export default function Tabbar(props) {const { tabData , cur…

使用pip下载第三方软件包报错超时处理方法

报错如下&#xff1a; WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by ‘ReadTimeoutEr ror(“HTTPSConnectionPool(host‘files.pythonhosted.org’, port443): Read timed out. (read timeout15)”)’: /p…