首页 android子线程会自动销毁吗,Android-中的子线程解析

android子线程会自动销毁吗,Android-中的子线程解析

举报
开通vip

android子线程会自动销毁吗,Android-中的子线程解析  android子线程会自动销毁吗,Android中的“子线程”解析  Android中线程可分为主线程和子线程两类,其中主线程也就是UI线程,它的主要这作用就是运行四大组件、处理界面交互。子线程则主要是处理耗时任务,也是我们要重点分析的。首先Java中的各种线程在Android里是通用的,Android特有的线程形态也是基于Java的实现的,所以有必要先简单的了解下Java中的线程,本文主要包括以下内容:Thread、RunnableCallable、Future线程池IntentService、Handler...

android子线程会自动销毁吗,Android-中的子线程解析
  android子线程会自动销毁吗,Android中的“子线程”解析  Android中线程可分为主线程和子线程两类,其中主线程也就是UI线程,它的主要这作用就是运行四大组件、处理界面交互。子线程则主要是处理耗时任务,也是我们要重点分析的。首先Java中的各种线程在Android里是通用的,Android特有的线程形态也是基于Java的实现的,所以有必要先简单的了解下Java中的线程,本文主要包括以下内容:Thread、RunnableCallable、Future线程池IntentService、HandlerThreadAsyncTask一、Thread、Runnable在Java中要创建子线程可以直接继承Thread类,重写run()方法:publicclassMyThreadextendsThread{@Overridepublicvoidrun(){}}//启动线程newMyThread().start();或者实现Runnable接口,然后用Thread执行Runnable,这种方式比较常用:publicclassMyRunnableimplementsRunnable{@Overridepublicvoidrun(){}}//启动线程newThread(newMyRunnable()).start();简单的 总结 初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf 下:Runnable可以实现多个线程共享资源,可以参考网上卖票的例子Runnable可以避免Java中的单继承的限制无法直接得到任务的执行结果二、Callable、FutureCallable和Runnable类似,都可以用来处理具体的耗时任务逻辑的,但是但具体的差别在哪里呢?看一个小例子:定义MyCallable实现了Callable接口,和之前Runnable的run()方法对比下,call()方法是有返回值的哦,泛型就是返回值的类型:publicclassMyCallableimplementsCallable{@OverridepublicStringcall()throwsException{Log.e("call","taskstart");Thread.sleep(2000);Log.e("call","taskfinish");return"hellothread";}}一般会通过线程池来执行Callable(线程池相关内容后边会讲到),执行结果就是一个Future对象://创建一个线程池ExecutorServicecachedThreadPool=Executors.newCachedThreadPool();//执行任务Futureresult=cachedThreadPool.submit(newMyCallable());try{//获取执行结果Log.e("result",result.get());}catch(InterruptedExceptione){e.printStackTrace();}catch(ExecutionExceptione){e.printStackTrace();}可以看到,通过线程池执行MyCallable对象返回了一个Future对象,取出执行结果。Future是一个接口,从其内部的方法可以看出它提供了取消任务(有坑!!!)、判断任务是否完成、获取任务结果的功能:publicinterfaceFuture{booleancancel(booleanmayInterruptIfRunning);booleanisCancelled();booleanisDone();Vget()throwsInterruptedException,ExecutionException;Vget(longtimeout,TimeUnitunit)throwsInterruptedException,ExecutionException,TimeoutException;}Future接口有一个FutureTask实现类,同时FutureTask也实现了Runnable接口,并提供了两个构造函数:publicFutureTask(Callablecallable){}publicFutureTask(Runnablerunnable,Vresult){}用FutureTask一个 参数 转速和进给参数表a氧化沟运行参数高温蒸汽处理医疗废物pid参数自整定算法口腔医院集中消毒供应 的构造函数来改造下上边的例子:ExecutorServicecachedThreadPool=Executors.newCachedThreadPool();FutureTaskfutureTask=newFutureTask<>(newMyCallable());cachedThreadPool.submit(futureTask);try{Log.e("result",futureTask.get());}catch(InterruptedExceptione){e.printStackTrace();}catch(ExecutionExceptione){e.printStackTrace();}FutureTask内部有一个done()方法,代 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf Callable中的任务已经结束,可以用来获取执行结果:FutureTaskfutureTask=newFutureTask(newMyCallable()){@Overrideprotectedvoiddone(){super.done();try{Log.e("result",get());}catch(InterruptedExceptione){e.printStackTrace();}catch(ExecutionExceptione){e.printStackTrace();}}};所以Future+Callable的组合可以更方便的获取子线程任务的执行结果,更好的控制任务的执行,主要的用法先说这么多了,其实AsyncTask内部也是类似的实现!注意,Future并不能取消掉运行中的任务,这点在后边的AsyncTask解析中有提到。三、线程池Java中线程池的具体的实现类是ThreadPoolExecutor,继承了Executor接口,这些线程池在Android中也是通用的。使用线程池的好处:方便对线程进行管理线程复用,避免大量创建、销毁线程带来的性能开销可控制线程的最大并发数,避免线程之间抢占资源造成阻塞常用的构造函数如下:publicThreadPoolExecutor(//线程池的核心线程数,如果设置allowCoreThreadTimeOut属性为true,当闲置时间大于keepAliveTime会被终止掉,否则会一直存活不受keepAliveTime影响intcorePoolSize,//线程池能容纳的最大线程数,超过该数量的将会被阻塞intmaximumPoolSize,//线程闲置的超时时间longkeepAliveTime,//超时时间的单位TimeUnitunit,//线程池的任务队列,保存通过execute()提交的Runnable,如果任务队列已满,则后续任务不被执行BlockingQueueworkQueue,//创建新的线程ThreadFactorythreadFactory){}一个常规线程池可以按照如下方式来实现:publicclassThreadPool{//CPU核心数privateintCPU_COUNT=Runtime.getRuntime().availableProcessors();//可同时下载的任务数(核心线程数)privateintCORE_POOL_SIZE=CPU_COUNT;//线程池容纳的最大线程数privateintMAX_POOL_SIZE=2*CPU_COUNT+1;//超时时间privatelongKEEP_ALIVE=10L;privateThreadPoolExecutorTHREAD_POOL_EXECUTOR;privateThreadFactorysThreadFactory=newThreadFactory(){privatefinalAtomicIntegermCount=newAtomicInteger();@OverridepublicThreadnewThread(@NonNullRunnablerunnable){returnnewThread(runnable,"download_task#"+mCount.getAndIncrement());}};privateThreadPool(){}publicstaticThreadPoolgetInstance(){returnSingletonHolder.instance;}privatestaticclassSingletonHolder{privatestaticfinalThreadPoolinstance=newThreadPool();}privateThreadPoolExecutorgetThreadPoolExecutor(){if(THREAD_POOL_EXECUTOR==null){THREAD_POOL_EXECUTOR=newThreadPoolExecutor(CORE_POOL_SIZE,MAX_POOL_SIZE,KEEP_ALIVE,TimeUnit.SECONDS,newLinkedBlockingDeque(),sThreadFactory);}returnTHREAD_POOL_EXECUTOR;}publicvoidexecute(Runnablecommand){getThreadPoolExecutor().execute(command);}}执行任务:ThreadPool.getInstance().execute(newRunnable(){@Overridepublicvoidrun(){//dosomething}});基于ThreadPoolExecutor,系统扩展了几类具有新特性的线程池://创建一个线程数量固定的线程池,核心线程数就是线程池能容纳的最大线程数,同时线程将一直存活,除非线程池被关闭//如果任何线程在执行期间因故障而终止,在关闭之前,如果需要,新线程将取代它执行后续任务,//如果所有线程都处于活动状态,新来的任务需要等待,直到有空闲线程ExecutorServicefixedThreadPool=Executors.newFixedThreadPool();//该线程池只有非核心线程,数量为Integer.MAX_VALUE//按需创建线程,没有空闲线程时会创建新线程,否则复用空闲线程,任何任务都会被立即执行//超时时间为60秒,当线程池长时间闲置时线程都会被终止掉,几乎不占用系统资源//任务队列比较特殊是SynchronousQueue,而非一般的LinkedBlockingQueueExecutorServicecachedThreadPool=Executors.newCachedThreadPool();//创建一个核心线程数固定的线程池,可容纳的最大线程数量为Integer.MAX_VALUE,非核心线程的超时时间为0//主要用于执行定时任务和有固定周期的任务ExecutorServicescheduledThreadPool=Executors.newScheduledThreadPool();//该线程池中只有一个核心线程,所有任务都通过该线程执行//任务之间不用考虑线程同步的问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 ExecutorServicesingleThreadExecutor=Executors.newSingleThreadExecutor();//Androidapilevel24新加的//会根据所需的并行层次来动态创建和关闭线程,试图减少任务队列的大小,所以比较适于高负载的环境//也比较适用于当执行的任务会创建更多任务,如递归任务ExecutorServiceworkStealingPool=Executors.newWorkStealingPool();线程池可以通过execute()、submit()方法开始执行任务,主要差别从方法的声明就可以看出,由于submit()有返回值,可以方便得到任务的执行结果:voidexecute(Runnablecommand)Future>submit(Runnabletask)Futuresubmit(Callabletask)Futuresubmit(Runnabletask,Tresult)要关闭线程池可以使用如下方法:voidshutdown()ListshutdownNow()四、IntentService、HandlerThread1、基本使用IntentService是Android中一种特殊的Service,可用于执行后台耗时任务,任务结束时会自动停止,由于属于系统的四大组件之一,相比一般线程具有较高的优先级,不容易被杀死。用法和普通Service基本一致,只需要在onHandleIntent()中处理耗时任务即可:publicclassDomainServiceextendsIntentService{publicDomainService(){super("DomainService");}@OverrideprotectedvoidonHandleIntent(@NullableIntentintent){//处理耗时任务}@OverridepublicvoidonDestroy(){super.onDestroy();}}至于HandlerThread,它是IntentService内部实现的重要部分,细节内容会在IntentService源码中说到。2、源码解析IntentService首次创建被启动的时候其生命周期方法onCreate()会先被调用,所以我们从这个方法开始分析:@OverridepublicvoidonCreate(){super.onCreate();HandlerThreadthread=newHandlerThread("IntentService["+mName+"]");thread.start();mServiceLooper=thread.getLooper();mServiceHandler=newServiceHandler(mServiceLooper);}这里出现了HandlerThread和ServiceHandler两个类,先搞明白它们的作用,以便后续的分析。首先看HandlerThread的核心实现:publicclassHandlerThreadextendsThread{publicHandlerThread(Stringname){super(name);mPriority=Process.THREAD_PRIORITY_DEFAULT;}@Overridepublicvoidrun(){mTid=Process.myTid();Looper.prepare();synchronized(this){mLooper=Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid=-1;}首先它继承了Thread类,可以当做子线程来使用,并在run()方法中创建了一个消息循环系统、开启消息循环。ServiceHandler是IntentService的内部类,继承了Handler,具体内容后续分析:privatefinalclassServiceHandlerextendsHandler{}现在回过头来看onCreate()方法主要是一些初始化的操作,首先创建了一个thread对象,并启动线程,然后用其内部的Looper对象创建一个mServiceHandler对象,将子线程的Looper和ServiceHandler建立了绑定关系,这样就可以使用mServiceHandler将消息发送到子线程去处理了。生命周期方法onStartCommand()方法会在IntentService每次被启动时调用,一般会这里处理启动IntentService传递Intent解析携带的数据:@OverridepublicintonStartCommand(@NullableIntentintent,intflags,intstartId){onStart(intent,startId);returnmRedelivery?START_REDELIVER_INTENT:START_NOT_STICKY;}又调用了start()方法:@OverridepublicvoidonStart(@NullableIntentintent,intstartId){Messagemsg=mServiceHandler.obtainMessage();msg.arg1=startId;msg.obj=intent;mServiceHandler.sendMessage(msg);}就是用mServiceHandler发送了一条包含startId和intent的消息,消息的发送还是在主线程进行的,接下来消息的接收、处理就是在子线程进行的:privatefinalclassServiceHandlerextendsHandler{publicServiceHandler(Looperlooper){super(looper);}@OverridepublicvoidhandleMessage(Messagemsg){onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}}当接收到消息时,通过onHandleIntent()方法在子线程处理intent对象,onHandleIntent()方法执行结束后,通过stopSelf(msg.arg1)等待所有消息处理完毕后终止服务。为什么消息的处理是在子线程呢?这里涉及到Handler的内部消息机制,简单的说,因为ServiceHandler使用的Looper对象就是在HandlerThread这个子线程类里创建的,并通过Looper.loop()开启消息循环,不断从消息队列(单链表)中取出消息,并执行,截取loop()的部分源码:for(;;){Messagemsg=queue.next();//mightblockif(msg==null){//Nomessageindicatesthatthemessagequeueisquitting.return;}msg.target.dispatchMessage(msg);}dispatchMessage()方法间接会调用handleMessage()方法,所以最终onHandleIntent()就在子线程中划线执行了,即HandlerThread的run()方法。这就是IntentService实现的核心,通过HandlerThread+Hanlder把启动IntentService的Intent从主线程切换到子线程,实现让Service可以处理耗时任务的功能!五、AsyncTask1、基本使用AsyncTask是Android中轻量级的异步任务抽象类,它的内部主要由线程池以及Handler实现,在线程池中执行耗时任务并把结果通过Handler机制中转到主线程以实现UI操作。典型的用法如下:/***三个泛型参数Params、Progress、Result分别表示耗时任务输入参数类型、进度类型、返回的结果类型*/publicclassDownloadAsyncTaskextendsAsyncTask{/***在主线程执行,可在耗时任务开始前做一些准备工作*/@OverrideprotectedvoidonPreExecute(){super.onPreExecute();Log.e("onPreExecute","downloadprepare");}/***在线程池中执行耗时任务**@paramurls输入参数*@return耗时任务的结果*/@OverrideprotectedStringdoInBackground(String...urls){Stringurl="";for(Stringtemp:urls){//执行耗时任务try{for(inti=0;i<=100;i+=10){//publishProgress()用来更新任务进度,会调用onProgressUpdate()方法publishProgress(i);Thread.sleep(20);}}catch(InterruptedExceptione){e.printStackTrace();}url=temp;}returnurl;}/***在主线程执行,进度更新时会被调用**@paramvaluesvalues[0]代表进度*/@OverrideprotectedvoidonProgressUpdate(Integer...values){super.onProgressUpdate(values);Log.e("onProgressUpdate",values[0]+"%");}/***在主线程执行,耗时任务执行结束**@paramurldoInBackground()的返回值*/@OverrideprotectedvoidonPostExecute(Stringurl){super.onPostExecute(url);Log.e("onPostExecute",url+"downloadfinish");}}从Android3.0开始,AsyncTask默认是串行执行的:newDownloadAsyncTask().execute("url-1");newDownloadAsyncTask().execute("url-2");如果需要并行执行可以这么做:newDownloadAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"url-1");newDownloadAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"url-2");2、源码解析AsyncTask的源码不多,还是比较容易理解的。根据上边的用法,可以从execute()方法开始我们的分析:@MainThreadpublicfinalAsyncTaskexecute(Params...params){returnexecuteOnExecutor(sDefaultExecutor,params);}看到@MainThread注解了吗?所以execute()方法需要在主线程执行哦!进而又调用了executeOnExecutor():publicfinalAsyncTaskexecuteOnExecutor(Executorexec,Params...params){if(mStatus!=Status.PENDING){switch(mStatus){caseRUNNING:thrownewIllegalStateException("Cannotexecutetask:"+"thetaskisalreadyrunning.");caseFINISHED:thrownewIllegalStateException("Cannotexecutetask:"+"thetaskhasalreadybeenexecuted"+"(ataskcanbeexecutedonlyonce)");}}mStatus=Status.RUNNING;onPreExecute();mWorker.mParams=params;exec.execute(mFuture);returnthis;}可以看到,当任务正在执行或者已经完成,如果又被执行会抛出异常!回调方法onPreExecute()最先被执行了。传入的sDefaultExecutor参数,是一个自定义的串行线程池对象,所有任务在该线程池中排队执行:privatestaticclassSerialExecutorimplementsExecutor{finalArrayDequemTasks=newArrayDeque();RunnablemActive;publicsynchronizedvoidexecute(finalRunnabler){mTasks.offer(newRunnable(){publicvoidrun(){try{r.run();}finally{scheduleNext();}}});if(mActive==null){scheduleNext();}}protectedsynchronizedvoidscheduleNext(){if((mActive=mTasks.poll())!=null){THREAD_POOL_EXECUTOR.execute(mActive);}}}可以看到SerialExecutor线程池仅用于任务的排队,THREAD_POOL_EXECUTOR线程池才是用于执行真正的任务,就是我们线程池部分讲到的ThreadPoolExecutor:static{ThreadPoolExecutorthreadPoolExecutor=newThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE_SECONDS,TimeUnit.SECONDS,sPoolWorkQueue,sThreadFactory);threadPoolExecutor.allowCoreThreadTimeOut(true);THREAD_POOL_EXECUTOR=threadPoolExecutor;}再回到executeOnExecutor()方法中,那么exec.execute(mFuture)就是触发线程池开始执行任务的操作了。那executeOnExecutor()方法中的mWorker是什么?mFuture是什么? 答案 八年级地理上册填图题岩土工程勘察试题省略号的作用及举例应急救援安全知识车间5s试题及答案 在AsyncTask的构造函数中:publicAsyncTask(@NullableLoopercallbackLooper){mHandler=callbackLooper==null||callbackLooper==Looper.getMainLooper()?getMainHandler():newHandler(callbackLooper);mWorker=newWorkerRunnable(){publicResultcall()throwsException{mTaskInvoked.set(true);Resultresult=null;try{Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspectionuncheckedresult=doInBackground(mParams);Binder.flushPendingCommands();}catch(Throwabletr){mCancelled.set(true);throwtr;}finally{postResult(result);}returnresult;}};mFuture=newFutureTask(mWorker){@Overrideprotectedvoiddone(){try{postResultIfNotInvoked(get());}catch(InterruptedExceptione){android.util.Log.w(LOG_TAG,e);}catch(ExecutionExceptione){thrownewRuntimeException("AnerroroccurredwhileexecutingdoInBackground()",e.getCause());}catch(CancellationExceptione){postResultIfNotInvoked(null);}}};}原来mWorker是一个Callable对象,mFuture是一个FutureTask对象,继承了Runnable接口。所以mWorker的call()方法会在mFuture的run()方法中执行,所以mWorker的call()方法在线程池得到执行!同时doInBackground()方法就在call()中方法,所以我们自定义的耗时任务逻辑得到执行,不就是我们第二部分讲的那一套吗!doInBackground()的返回值会传递给postResult()方法:privateResultpostResult(Resultresult){@SuppressWarnings("unchecked")Messagemessage=getHandler().obtainMessage(MESSAGE_POST_RESULT,newAsyncTaskResult(this,result));message.sendToTarget();returnresult;}就是通过Handler将最终的耗时任务结果从子线程发送到主线程,具体的过程是这样的,getHandler()得到的就是AsyncTask构造函数中初始化的mHandler,mHander又是通过getMainHandler()赋值的:privatestaticHandlergetMainHandler(){synchronized(AsyncTask.class){if(sHandler==null){sHandler=newInternalHandler(Looper.getMainLooper());}returnsHandler;}}可以在看到sHandler是一个InternalHandler类对象:privatestaticclassInternalHandlerextendsHandler{publicInternalHandler(Looperlooper){super(looper);}@SuppressWarnings({"unchecked","RawUseOfParameterizedType"})@OverridepublicvoidhandleMessage(Messagemsg){AsyncTaskResult>result=(AsyncTaskResult>)msg.obj;switch(msg.what){caseMESSAGE_POST_RESULT://Thereisonlyoneresultresult.mTask.finish(result.mData[0]);break;caseMESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}所以getHandler()就是在得到在主线程创建的InternalHandler对象,所以就可以完成耗时任务结果从子线程到主线程的切换,进而可以进行相关UI操作了。当消息是MESSAGE_POST_RESULT时,代表任务执行完成,finish()方法被调用:privatevoidfinish(Resultresult){if(isCancelled()){onCancelled(result);}else{onPostExecute(result);}mStatus=Status.FINISHED;}如果任务没有被取消的话执行onPostExecute(),否则执行onCancelled()。如果消息是MESSAGE_POST_PROGRESS,onProgressUpdate()方法被执行,根据之前的用法可以onProgressUpdate()的执行需要我们手动调用publishProgress()方法,就是通过Handler来发送进度数据:protectedfinalvoidpublishProgress(Progress...values){if(!isCancelled()){getHandler().obtainMessage(MESSAGE_POST_PROGRESS,newAsyncTaskResult(this,values)).sendToTarget();}}进行中的任务如何取消呢?AsyncTask提供了一个cancel(booleanmayInterruptIfRunning),参数代表是否中断正在执行的线程任务,但是呢并不靠谱,cancel()的方法注释中有这么一段:Callingthismethodwillresultin{@link#onCancelled(Object)}beinginvokedontheUIthreadafter{@link#doInBackground(Object[])}returns.Callingthismethodguaranteesthat{@link#onPostExecute(Object)}isneverinvoked.Afterinvokingthismethod,youshouldcheckthevaluereturnedby{@link#isCancelled()}periodicallyfrom{@link#doInBackground(Object[])}tofinishthetaskasearlyaspossible.大致意思就是调用cancel()方法后,onCancelled(Object)回调方法会在doInBackground()之后被执行而onPostExecute()将不会被执行,同时你应该doInBackground()回调方法中通过isCancelled()来检查任务是否已取消,进而去终止任务的执行!所以只能自己动手了:@OverrideprotectedStringdoInBackground(String...urls){.........if(isCancelled()){//手动抛出异常,并自己捕获或者直接return}.........}AsyncTask整体的实现流程就这些了,源码是最好的老师,自己跟着源码走一遍有些问题可能就豁然开朗了! -全文完-
本文档为【android子线程会自动销毁吗,Android-中的子线程解析】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
个人认证用户
永兴文档
暂无简介~
格式:doc
大小:32KB
软件:Word
页数:49
分类:互联网
上传时间:2023-06-18
浏览量:17