android應(yīng)用開發(fā)實(shí)踐教程-第9章java并發(fā)編程_第1頁
android應(yīng)用開發(fā)實(shí)踐教程-第9章java并發(fā)編程_第2頁
android應(yīng)用開發(fā)實(shí)踐教程-第9章java并發(fā)編程_第3頁
android應(yīng)用開發(fā)實(shí)踐教程-第9章java并發(fā)編程_第4頁
android應(yīng)用開發(fā)實(shí)踐教程-第9章java并發(fā)編程_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余28頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

目第一部分基礎(chǔ) 第9章Java并發(fā)編 Java線簡 Executor與 “3G( 9.7本章小 習(xí)題 第9Java本章導(dǎo)讀:Android的應(yīng)用程序支持多線程,多線程編程為我們充分利用系統(tǒng)資源提供UI和耗時操作提供了途徑,提升了安卓用戶的使用體驗(yàn)。線程((2Executor;Javajdk1.4jdk版本中,關(guān)于線的使用需要自己動手實(shí)現(xiàn)。jdk1.5出現(xiàn)后,并發(fā)線程這塊發(fā)生了根本的變化,最重APIjdk1.5Executor來啟動線程比用Threadstart()更好。我們可以很容易控制線程的啟動、執(zhí)行和關(guān)閉過程,還可以很容易使用線的特性,這歸結(jié)于jdk1.5之后加入了java.util.concurrent包。這個包中主要介紹java線程以及線的使用,為我們在開發(fā)中處理線程問題提供了非常大的java.util.concurrent包含了并發(fā)編程中很常用的實(shí)用工具類。Executor是一個簡單的標(biāo)準(zhǔn)化接口,用于定義類似于線程的自定義子系統(tǒng),包括線、異步IO和輕量級任務(wù)框架。根據(jù)所使用的具體Executor類的不同,可能在新創(chuàng)建的線程中,現(xiàn)有的任務(wù)執(zhí)行()提供了多個完整的異步任務(wù)執(zhí)行框架。ExecutorService管理任務(wù)的排隊(duì)和安排,并允許受的支持。ExecutorService提供了安排異步執(zhí)行的方法,可執(zhí)行由Callable表示的任何函數(shù),結(jié)果類似于Runnable。Future返回函數(shù)的結(jié)果,允許確定執(zhí)行是否完成,并提供取消執(zhí)行的方法。RunnableFuture是擁有run方法的Future,run方法執(zhí)行時將設(shè)置其結(jié)果。類ThreadPoolExecutor和ScheduledThreadPoolExecutor提供可調(diào)的、靈活的線。ExecutorsExecutor的常見類型和配置的工廠方法,以及使用它們的幾種實(shí)用 publicinterfacepublicinterface}ExecutorRunnableExecutor而不是顯式地創(chuàng)建線程。例如,可能會使用以下方法,而不是為一組任務(wù)中的每個任務(wù)調(diào)用newExecutorexecutor=anExecutor;Executorexecutor=anExecutor;{publicvoidexecute(Runnabler){}}{publicvoidexecute(Runnabler){newThread(r).start();}}ExecutorService繼承了Executor,我們看一下ExecuteService{voidshutdown();booleanisShutdown();booleanbooleanawaitTermination(longtimeout,TimeUnitunit)throwsInterruptedException;<T>Future<T>submit(Runnabletask,Tresult);Future<?>submit(Runnabletask);throwsthrows<T>TinvokeAny(Collection<?extendsCallable<T>>throwsthrows<T>TinvokeAny(Collection<?extendsCallable<T>>tasks)throwsInterruptedException,ExecutionException;}shutdown()方法在終止前允許執(zhí)行以前提交的任務(wù),而shutdownNow()方法等待任ExecutorService以允許回收其資通過創(chuàng)建并返回一個可用于取消執(zhí)行和/Futuresubmit擴(kuò)展了基本方法Executor.execute(java.lang.Runnable)。線大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小。 CachedThreadPool模式首先會按照需要創(chuàng)建足夠多的線程來執(zhí)行任務(wù)(Task)。隨著程序任務(wù)。(code9CachedThreadPoolDemo工程)首先,任務(wù)定義如下(實(shí)現(xiàn)了Runnable接口,并且復(fù)寫了run方法publicclassLiftOffimplementsRunnable protectedprotectedintcountDown=10;//DefaultprivatestaticinttaskCount=0;privatefinalintid=taskCount++;publicLiftOff(){}publicLiftOff(int{this.countDown=}publicStringstatus()return"#"+id+"("+(countDown>0?countDown:"LiftOff!")+")}publicvoidrun()while(countDown-->}}}publicclassCachedThreadPoolpublicclassCachedThreadPoolExecutorServiceexec=Executors.newCachedThreadPool();for(inti=0;i<10;i++){}}}10CachedThreadPool模式,execLiftOff(TaskFixedThreadPool模式創(chuàng)建一個定長線,可控制線程最大并發(fā)數(shù),超出的線程會在任務(wù)(如果有的話CachedThreadPool是不同的,CachedThreadPool模FixedThreadPool模式下最多的線程數(shù)ExecutorServicefixedThreadPool=Executors.newFixedThreadPool(3);for(inti=0;i<18;i++){finalintindex=i;{publicvoidrun(){{);ExecutorServicefixedThreadPool=Executors.newFixedThreadPool(3);for(inti=0;i<18;i++){finalintindex=i;{publicvoidrun(){{);{}}}}}SingleThreadExecutor模式只會創(chuàng)建一個線程。它和FixedThreadPool比較類似,不過線SingleThreadExecutor的話,那么這些任務(wù)會被保存在SingleThreadExecutor模式可以保證只有一個任務(wù)會被執(zhí)行。這種特點(diǎn)可以被用來處理publicstaticvoidpublicstaticvoidmain(String[]args)ExecutorServiceexec=for(inti=0;i<2;{exec.execute(new}}ScheduledThreadPool模式創(chuàng)建一個定長線,支持定時及周期性任務(wù)執(zhí)行。publicstaticvoidmain(String[]args)publicvoidrun()System.out.println("delay1seconds,andexcuteevery3}},1,3,}}行每個提交的任務(wù),通常使用Executors工廠方法配置。)和Executors.newSingleThreadExecutor()(單個線程,它們均為大多數(shù)使用場景 unit,BlockingQueue<Runnable> ThreadPoolExecutor(intcorePoolSize, intumPoolSize, longkeepAliveTime, BlockingQueue<Runnable>workQueue,RejectedExecutionHandlerhandler)說明:用給定的初始參數(shù)和默認(rèn)的線程工廠創(chuàng)建新的ThreadPoolExecutor(intcorePoolSize, intumPoolSize, longkeepAliveTime, BlockingQueue<Runnable>workQueue,ThreadFactorythreadFactory)ThreadPoolExecutor(intcorePoolSize, intumPoolSize, longkeepAliveTime, BlockingQueue<Runnable>workQueue,ThreadFactorythreadFactory,RejectedExecutionHandlerhandler)的在JDK幫助文檔中對ThreadPoolExecutor構(gòu)造方法的參數(shù)是這樣說明的:corePoolSize:池中所保存的線程數(shù),包括空閑線程。umPoolSize:publicclassExecutorspublicclassExecutors{returnnewThreadPoolExecutor(nThreads,0L,new}{returnnewFinalizableDelegatedExecutorService(newThreadPoolExecutor(1,1,0L,new}60L,new}…}關(guān)于和最大池大小:ThreadPoolExecutor將根據(jù)corePoolSize設(shè)置的邊界自動調(diào)整池大小。當(dāng)新任務(wù)在方法execute(java.lang.Runnable)中提交時,如果運(yùn)行的線程少于corePoolSize而少于umPoolSize,則僅當(dāng)隊(duì)列滿時才創(chuàng)建新線程。如果設(shè)置的corePoolSize和umPoolSize相同,則創(chuàng)建了固定大小的線。如果將umPoolSize設(shè)置為基本的值(如Intege.MAX_ALUE,則允許池適應(yīng)任意數(shù)setCorePoolSize(int)和setumPoolSize(int)進(jìn)行動態(tài)更改。corePoolSize的線程,則這些多出的線BlockingQueue都可用于傳輸和保持提交的任務(wù)??梢允褂么岁?duì)程超出umPoolSize,在這種情況下,任務(wù)將被。SynchronousQueue,它將任務(wù)直接提交給線程而不保持它們。后才能繼續(xù)添加。在這里不是線程便是新創(chuàng)建的線程。)直接提交通常要求LinkedBlockingQueuenewFixedThreadPool,根據(jù)前文提到的規(guī)則:如果運(yùn)行的線程少于corePoolSizeExecutor始終首選添加新的線程,而不進(jìn)行排隊(duì)。那么當(dāng)任務(wù)繼續(xù)增加,會發(fā)生什么呢?如果運(yùn)行的線程等于或多于corePoolSize,則Executor始終首 SynchronousQueue那樣有其自身的特點(diǎn),對于隊(duì)列來說,總是可以加入的(資源耗盡,當(dāng)然另當(dāng)別論。換句說,也不會觸發(fā)產(chǎn)生新的線程!corePoolSize大小的線程數(shù)會一直corePoolSize(因此,umPoolSize的值也就無效了。)當(dāng)每個任務(wù)當(dāng)使用有限的umPoolSizes時,有界隊(duì)列(ArrayBlockingQueue)有助于防止CPU使用率、操作系統(tǒng)資源和上下文切換開銷,但是可關(guān)于被的任務(wù):當(dāng)Executor已經(jīng)關(guān)閉,并且Executor將有限邊界用于最大線。在以上兩種情況下,execute方法都將調(diào)用其RejectedExecutionHandler的java.util.concurrent.ThreadPoolExecutor)方法。}staticvoiduseThreadPool(intcount)finalList<Integer>list=newlongstartTime=ThreadPoolExecutortpe=newThreadPoolExecutor(1,1,finalRandomrandomnew //for(inti=0;i<count;{tpe.execute(newRunnable(){publicvoid{}}try, {}}staticvoiduseOneThread(intcount)finalList<Integer>list=newlongstartTime=finalRandomrandomnew //for(inti=0;i<count;{Threadthread=new{publicvoid{}try{}}我們看到在count參數(shù)為20000時,使用線 還有一個是使用線提交任務(wù)的例子,工程(源碼) 結(jié)構(gòu)見圖9-1。 圖9-2Future模式舉的時間間隔內(nèi)打印executor信息。程序的是WorkerPool的main方法。在初始化ThreadPoolExecutor時,我們保持初242。因此如果已經(jīng)有四個正在執(zhí)行的任務(wù)而此時分配來任務(wù)的話,工作隊(duì)列將僅僅保留新任務(wù)中的兩個,其他的將會被RejectedExecutionHandlerImpl處理。 接口Data的主要作用是:返回?cái)?shù)據(jù)的接口。提供了getResult()RealData。publicpublicclassTest{Clientclient=newDatadata=client.request("name"); try}catch(Exceptione)}System.out.println("數(shù)據(jù)="+ //真實(shí)數(shù)}}publicclasspublicclassClientpublicDatarequest(finalStringqueryStr)finalFutureDatafuture=newnewThread //publicvoidrun()RealDatarealData=newRealData(queryStr);}}}publicpublicinterfaceData String}{protectedRealDatarealData=null;protectedbooleanisReady=false;{if(isReady){}isReady=true; }{while(!isReady){try{}catch(Exceptione)}}return}}{protectedStringpublicRealData(Stringpara //StringBuffersb=newStringBuffer();for(inti=0;i<10;i++){try{}catch(Exceptione)}result=}}{return}}=說明:FutureDataRealData的包裝,是對真實(shí)數(shù)據(jù)的一個,封裝了獲取真實(shí)數(shù)=其它任何事兒,當(dāng)流程進(jìn)行到需要Future背后的對象時,可能有兩種情況:get()get(longtimeoutTimeUnitunit)通過同步阻塞方式等待對象就緒。實(shí)際運(yùn)行期是阻塞還是立即返回就取決于get()的調(diào)用時機(jī)和對象就緒的先java.util.concurrent.Callablejava.util.concurrent.FutureFuture模式。的目標(biāo)對象生成之后,將之設(shè)置到Future之中,而當(dāng)客戶端真正需要目標(biāo)對象時,目標(biāo)對publicinterface{Vcall()throwspublicinterface{Vcall()throws可以使用Callable完成某個費(fèi)時的工作,工作結(jié)束后傳回結(jié)果對象,例如求質(zhì)數(shù)。這里是在EclipseJavaEE中建立futuredemo_2工程,是JavaProject。publicclasspublicclassFutureDemopublicstaticvoidmain(String[]args)Callable<int[]>primeCallable=newPrimeCallable(1000);FutureTask<int[]>primeTask=newFutureTask<int[]>(primeCallable);Threadt=newThread(primeTask);try{ //( //for(intprime:primes){}}{{}}}{privateint{this.max=}publicint[]call()throws{int[]prime=newint[max+1];List<Integer>list=newArrayList<Integer>();for(inti=2;i<=max;i++)prime[i]=forinti2;i*imax;i這里可以改進(jìn)if(prime[i]==1){for(intj=2*i;j<=max;{if(j%i==prime[j]=}}}for(inti=2;i<max;{if(prime[i]==1){}}int[]p=newint[list.size()];for(inti=0;i<p.length;i++){p[i]=}return}}PrimeCallableFuture來獲得Callable執(zhí)行的結(jié)果,從而在未來的時間點(diǎn)獲得結(jié)果。2357111317192329…9419479539679712357111317192329…941947953967971977983991任務(wù)說項(xiàng)目講 圖9-3MobileMarketCity_3G_B工程 圖9-4MobileMarketCity_3G_B工程運(yùn)行界面com.mialab.marketcity包:主要包含主界面類MainA.mialab.marketcity.baseBaseA.mialab.marketcity.beans包:此包中放置的是實(shí)體類。 com.mialab.marketcity.views包:視圖(控件)類包。主要包含Screen.java、(MobileaketCit_3,只不過是從網(wǎng)絡(luò)異步加載的。主要運(yùn)行界面如圖9-4所示。網(wǎng)絡(luò)位置:,測 android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>擊寬帶進(jìn)入寬帶列表界面如上圖,但每一個item左側(cè)的是異步從網(wǎng)絡(luò)加載的。{privateLayoutInflatermInflater;privateListViewlistView;…mImageWorker=getImageWorker();mImageWorker.setOnScreen(Constants.APP_TAG,true);marketcity_BroadBand_Adapter=newmImageWorker,listView);…}…}imgUrl="if載。}典型代碼及技術(shù)privateImageCacheprivateintloadingResId=0,errorResId=0,bgResId=0;privatevolatilebooleanonScreen=true;publicstaticintScreenWeith=privateHashMap<String,ImageCacheParams>params;privateHandlermHandler;publicstaticfinalintIO_BUFFER_SIZE=8*1024;privateOnHandleCacheListenermIHandleCache;{return}private{mHandler=newmImageCache=ImageCache.createCache();searchThreadPool=Executors.newFixedThreadPool(8);mIHandleCache=newOnHandleCacheListener(){publicvoidonSetImage(finalImageViewimageView,finalBitmapbitmap){{@Overridepublicvoidrun(){…}}{mHandler.post(newRunnable(){publicvoidrun()if(imageView!=null)…}}}}{SearchTasktask=getSearchTask(view);if(task!=null){finalStringtaskPath={}elsereturn}}return}privatevoidif||{searchThreadPool=searchThreadPool=}}}{}…}…}…}{Stringvolatilebooleanstop=intreqW=0;intintreqH= //stop=}publicSearchTask(finalStringpath,finalImageViewimageView,intw,inth,finalOnHandleCacheListenermIHandleCache){reqW=w;reqH=h;this.mIHandleCache=mIHandleCache;}publicvoidrun()…}…}須注意到:如果生成SearchTask對象,會含有弱 ImageView對象。以及boolean變量stop被為volatile。privateintdefaultId=0;privateinterrorResId=0;privateintbgresId=0;publicAsyncDrawable(intloadingRes,interrResId,intbgResid,SearchTasksearchTask){defaultId=loadingRes;bgresId=bgResid;}…} publicenum{// //////是否使用SD//是否在使用緩存前清理SDprivatestaticfinalbooleanDEFAULT_CLEAR_DISK_CACHE_ON_START=false;privateImageCacheParamsmImageCacheParams;privateDiskCache sd //{return}privateImageCache()}{}{mImageCacheParams=//Setupdisk…}//SetupmemorymMemoryCache=newLruCache<String,Bitmap>(cacheParams.memCacheSize){{return}}}} // if(data==null||bitmap==null)}if(mMemoryCache!=null&&mMemoryCache.get(data)=={mMemoryCache.put(data,bitmap);//Addtomemory}} if(mMemoryCache!=null)finalBitmapmemBitmap=mMemoryCache.get(path);if(memBitmap!=null){return}}return} //if(mMemoryCache!={}}//Aholderclassthatcontainscacheparameters.publicstaticclassImageCacheParams{publicbooleandiskCacheEnabled=DEFAULT_DISK_CACHE_ENABLED;publicintmemCacheSize=DEFAULT_MEM_CACHE_SIZE;publicbooleanclearDiskCacheOnStart=}…} 向的對象不會被回收,即使內(nèi)存不足的時候。當(dāng)強(qiáng)被置為NULL時,該對象象仍然占著內(nèi)存??傊?,我們不能保證可回收的對象被GC回收。GC算法以及GC運(yùn)行時可用的內(nèi)存數(shù)量。通俗地講,內(nèi)存空間足夠,GC就不會回收它;如果內(nèi)存空間不足了,就會回收這些對象的內(nèi)存。 publicclassTest //創(chuàng)建是在常量池//創(chuàng)建一個弱 str指向String對象WeakReference<String>wr=newWeakReference<String>(str);str=null; //輸出JAVA講義 //強(qiáng)制 //輸出null}}但是也有可能需要GC多次才能發(fā)現(xiàn)和釋放弱的對象。MyObjectobj=newMyObject();ReferenceQueuerq=newReferenceQueue();WeakReferencewr=newWeakReference(obj,rq);objMyObjectobj=newMyObject();ReferenceQueuerq=newReferenceQueue();WeakReferencewr=newWeakReference(obj,rq);obj rq.poll();如果被GC回收了,wr.get()返回NULL,rq.poll()返回對象的弱wr。在應(yīng)用程序UI界面加載一張是一件很簡單的事情,但是當(dāng)需要在界面上加載一大堆時,情況就變得復(fù)雜起來。在很多情況下,(比如使用ListView,GridView或者Vieger這樣的組件,屏幕上顯示的可以通過滑動屏幕等事件不斷地增加,最終導(dǎo)致OOM(outofmemory,內(nèi)存泄漏。片,它的主要算法原理是把最近使用的對象用強(qiáng)在LinkedHashMap中,并且把最,。LruCacheLruCache//intcacheSize=maxMemory/{//重寫此方法來衡量每 }}{if(getBitmapFromMemCache(key)==null){mMemoryCache.put(key,bitmap);}}{return}大概會占用1.5兆的空間(800*480*4= {finalStringimageKey=finalBitmapbitmap{finalStringimageKey=finalBitmapbitmap=getBitmapFromMemCache(imageKey);if(bitmap!=null){}else}} { nBackground(Integer...params){// 加,params[0],100,100);returnbitmap;}volatile修飾符告訴JVM,該變量的線程必須總是使自己對該變量的私有副本與內(nèi)在Javamainmemorymemory(例如寄存器。mainmemory中的值不一致的情況。memoryvolatilememoryvolatile{privatevolatilebooleanstop;publicvoidrun(){while(!stop)//dosome}} {stop=}}假如stop沒有被 為volatile,線程執(zhí)行run的時候檢查的是自己的副本,就不能及時得知其他線程已經(jīng)調(diào)用lMeToStop()修改了pleaseStop的值。}}ImageWorkerloadBitmap(finalStringpath,finalImageViewimageView,int…publicvoidloadBitmap(finalStringpath,final…publicvoidloadBitmap(finalStringpath,finalImageViewimageView,intloadingRes){loadBitmap(path,imageView,ScreenWeith/3,ScreenWeith/3,loadingRes,errorResId,bgResId);}publicvoidloadBitmap(finalStringpath,finalImageViewimageView,intw,inth,intloadingRes,interrRes,intbgRes){Bitmapresult=mImageCache.getBitmapFromMem(path);imageView.setBackgroundResource(bgRes>0?bgRes:0);if(result!=null&&!result.isRecycled()){finalSearchTasktask=newSearchTask(path,imageView,w,h,finalAsyncDrawableasyncDrawable=newAsyncDrawable(loadingRes,errRes,bgRes,task);if(!searchThreadPool.isTerminated()}}}}的cancelWork(imageView,path)方法,并判斷其返回值。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論