02線程與消息機(jī)制_第1頁
02線程與消息機(jī)制_第2頁
02線程與消息機(jī)制_第3頁
02線程與消息機(jī)制_第4頁
02線程與消息機(jī)制_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

、線程JAVA中的線程線程的概念線程是程序運(yùn)行的基本執(zhí)行單元。當(dāng)操作系統(tǒng)在執(zhí)行一個(gè)程序時(shí),會(huì)在系統(tǒng)中建立一個(gè)進(jìn)程,而在這個(gè)進(jìn)程中,必須至少建立一個(gè)線程(這個(gè)線程被稱為主線程)來作為這個(gè)程序運(yùn)行的入口點(diǎn)。因此,在操作系統(tǒng)中運(yùn)行的任何程序都至少有一個(gè)主線程。實(shí)現(xiàn)線程的方法在Java中建立線程有兩種方法,一種是繼承Thread類,另一種是實(shí)現(xiàn)Runnable接口,其實(shí)這兩種方法從本質(zhì)上說是一種方法,即都是通過Thread類來建立線程,并運(yùn)行run方法的。1.3線程的生命周期線程也同樣要經(jīng)歷開始(等待)、運(yùn)行、掛起和停止四種不同的狀態(tài)。這四種狀態(tài)都可以通過Thread類中的方法進(jìn)行控制。MainThread與WorkerThreadMainThread是主線程,又叫UI線程,WorkerThread是除了主線程之外的其他線程。原則上來講,worderthread里不允許操作UI。只有主線程mainthread可以。我們新建一個(gè)項(xiàng)目,在MainActivity里設(shè)置一個(gè)Button,點(diǎn)擊它時(shí)啟動(dòng)一個(gè)線程。publicclassMainActivityextendsActivity{privateTextviewtextview;privateButtonbutton;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textView=(TextView)findViewById(R.id.textview);button=(Button)findViewById(R.id.button);button.setonClickListener(newlistener());}classlistenerimplementsOnClickListener{@OverridepublicvoidonClick(Viewv){Threadt=newthread();t.start();}}//workerthreadclassthreadextendsThread{publicvoidrun(){try{Thread.sleep(1*1000);//阻塞當(dāng)前線程指定的時(shí)間}catch(InterruptedExceptione){e.printStackTrace();}textView.setText("來自于線程的修改");}}}上面是已經(jīng)寫好的代碼,我們?cè)诒O(jiān)聽器里實(shí)例化了一個(gè)自定義的Thread,調(diào)用了它的start方法。我們?cè)趖hread類的run方法里修改了textview的文本,即操作了UI。這個(gè)項(xiàng)目在運(yùn)行后,點(diǎn)擊按鈕,出現(xiàn)了如下錯(cuò)誤:這就是因?yàn)樵趙orderthread里操作了UI。但是有一些特殊的控件是允許的,比如progressBar。但如果把所有事情放在主線程里做,非常容易出現(xiàn)AR錯(cuò)誤,就是“應(yīng)用程序沒有響應(yīng)”。比如,我們把監(jiān)聽器里的代碼改成classlistenerimplementsOnClickListener{@OverridepublicvoidonClick(Viewv){try{Thread.sleep(10*1000);//讓主線程休眠十秒}catch(InterruptedExceptione){e.printStackTrace();}我們點(diǎn)擊按鈕,它接近于死機(jī)狀態(tài),過個(gè)幾秒,會(huì)出現(xiàn)如下畫面:S02E02_Thread01isn'tresponding.Doyouwanttocloseit?Wait OK這是因?yàn)橹骶€程阻塞了。結(jié)論:mainthread與worderthread各有所職。主線程主要用于接收用戶的輸入,以及將運(yùn)算結(jié)果反饋給用戶。主線程不允許阻塞,不要進(jìn)行耗時(shí)較長的操作,如訪問網(wǎng)絡(luò),大量讀寫等。這些操作必須放在worderthread中。mainthread負(fù)責(zé)Ul,worderthread負(fù)責(zé)運(yùn)算。提問:那么,worderthread中返回的信息如何影響UI呢?如何與mainthread通信呢?這需要用到handler。二、Handler1.運(yùn)行基本原理Handler、Looper和MessageQueue三者構(gòu)成了android的消息機(jī)制??聪聢D:MessageQueue是一種數(shù)據(jù)結(jié)構(gòu),符合先進(jìn)先出的原則,類似一個(gè)隧道。MessageQueue可以存放多個(gè)消息對(duì)象。Handler負(fù)責(zé)將消息對(duì)象加入到MessageQueue。Looper是一個(gè)循環(huán)器,不停的從MessageQueue中取出消息對(duì)象。如果MessageQueue中沒有消息對(duì)象,Looper會(huì)處于等待狀態(tài)。Looper將消息對(duì)象從MessageQueue中取出,再交給Handler處理。2.一個(gè)簡單的例子我們建立一個(gè)簡單的handler例子:新建一個(gè)項(xiàng)目,mainActivity里加一個(gè)button,設(shè)置監(jiān)聽器。接下來,我們定義一個(gè)handler,它需要繼承Handler。曲EY--tV%.注意:在引入包的時(shí)候,要選擇android.os.Handler。彈門cdroiij/OsH日nclle■”"0^java.util.logging.Handler然后,我們要復(fù)寫一個(gè)方法,是handleMessage方法。菜單欄Source->Override/ImplementMethodsSeiectmffthodstooverride-orimplement:J□gHandlerdi^pstchMessagetMessa-g-e)getMessageNameflMessage)handleWessagefMessage)I|QsendMestageAtTime(Menage,long)□etcrStringOD-鬥OObject然后我們聲明一handler對(duì)象privateHandlerhandler;在oncreate里給它賦值handler=newhandler();當(dāng)用戶點(diǎn)擊按鈕時(shí),我們創(chuàng)建一個(gè)消息對(duì)象,并使用handler發(fā)送該對(duì)象。監(jiān)聽器里代碼如下:classlistenerimplementsOnClickListener{@OverridepublicvoidonClick(Viewv){Messagemsg=handler.obtainMessage();//獲取一個(gè)消息對(duì)象msg.what=2;//給message的一個(gè)屬性賦值handler.sendMessage(msg);//用handler發(fā)送這個(gè)對(duì)象至Umessagequeue中去}}一旦messagequeue里有消息對(duì)象了,looper立刻將消息對(duì)象取出,找到與消息對(duì)象對(duì)應(yīng)的handler,然后調(diào)用handler對(duì)象的handlerMessage方法,處理消息對(duì)象。這時(shí),我們回到自定義的handler的handlerMessage方法,填充代碼:classhandlerextendsHandler{@OverridepublicvoidhandleMessage(Messagemsg){intwhat=msg.what;System.out.println(what);}}三、通過Handler實(shí)現(xiàn)線程間的通信l.workerthread向mainthread發(fā)送消息前面的例子是把handler放在主線程中運(yùn)行?,F(xiàn)在做另外一個(gè)例子,在主線程中實(shí)現(xiàn)Handler的handleMessage方法,在workerthread中通過handler發(fā)送消息。還是新建一個(gè)項(xiàng)目,放一個(gè)按鈕和文本,點(diǎn)擊按鈕后啟動(dòng)一個(gè)線程,讓這個(gè)線程休眠兩秒之后把文本的內(nèi)容修改掉。這個(gè)例子的實(shí)際意義在于,把休眠替換成訪問服務(wù)器就是開發(fā)中經(jīng)常用到的例子。準(zhǔn)備好按鈕和文本控件,我們來定義一個(gè)線程,在run函數(shù)里模擬了一次訪問服務(wù)器和取值://workerthreadclassthreadextendsThread{@Overridepublicvoidrun(){try{Thread.sleep(2*1000);//模擬訪問網(wǎng)絡(luò),休眠兩秒鐘}catch(InterruptedExceptione){e.printStackTrace();}Strings="從網(wǎng)絡(luò)中獲取的數(shù)據(jù)”;//模擬服務(wù)器的返回值}}然后在button的監(jiān)聽器里啟動(dòng)這個(gè)線程。classlistenerimplementsOnClickListener{@OverridepublicvoidonClick(Viewv){Threadt=newthread();t.start();}}重點(diǎn)來了,剛才我們定義的Thread是WorkerThread,它不能直接操作textview。我們需要Handler。先把它定義出來,先放著:classhandlerextendsHandler{@Override//workerthreadclassthreadextendsThread{@Overridepublicvoidrun(){//System.out.println("workerthread:"+Thread.currentThread().getName());//打印當(dāng)前線程的名字try{Thread.sleep(2*1000);//模擬訪問網(wǎng)絡(luò),休眠兩秒鐘}catch(InterruptedExceptione){e.printStackTrace();}Strings="從網(wǎng)絡(luò)中獲取的數(shù)據(jù)”;//模擬服務(wù)器的返回值Messagemsg=handler.obtainMessage();msg.obj=s;handler.sendMessage(msg);}}發(fā)送消息完成,接下來就是處理消息,我們回到自定義的handler,接收S,并寫入textview的文本:classhandlerextendsHandler{ OverridepublicvoidhandleMessage(Messagemsg){//System.out.println("handleMessage:"+Thread.currentThread().getName());//打印當(dāng)前線程的名字Strings=(String)msg.obj;textView.setText(s);}}這樣,我們實(shí)現(xiàn)了workerthread向mainthread發(fā)送消息。訪問網(wǎng)絡(luò)都是這樣操作的。2.mainthread向workerthread發(fā)送消息與前一個(gè)例子不同的是,我們需要在workerthread中準(zhǔn)備一個(gè)looper對(duì)象,并把handler定義在workerthread中。首先還是新建一個(gè)項(xiàng)目,準(zhǔn)備一個(gè)Button。然后定義一個(gè)線程://workerthreadclassthreadextendsThread{@Overridepublicvoidrun(){//準(zhǔn)備Looper對(duì)象Looper.prepare();//在workerthread中定義一個(gè)handler(匿名內(nèi)部類)handler=newHandler(){ verridepublicvoidhandleMessage(Messagemsg){}};//讓Looper開始循環(huán),不斷的從消息隊(duì)列中取出消息對(duì)象,如果沒有消息對(duì)象,則該線程阻塞。Looper.loop();}}這個(gè)線程有點(diǎn)復(fù)雜,首先是準(zhǔn)備一個(gè)Looper對(duì)象,然后用匿名內(nèi)部類的方式定義一個(gè)handler,為什么?因?yàn)閔andleMessage方法是定義在接收消息的一方。我們這個(gè)例子是要workerthread接收并處理消息。先把handleMessage的內(nèi)容空著,接下來,讓Looper開始循環(huán),它會(huì)不斷的從消息隊(duì)列中取出消息對(duì)象。接下來,我們?cè)谥骶€程里讓workerthread啟動(dòng):@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);butt

溫馨提示

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

評(píng)論

0/150

提交評(píng)論