明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

淺析Java多線程程序設(shè)計(jì)機(jī)制

[摘要]多線程是Java語(yǔ)言的一大特性,多線程就是同時(shí)存在N個(gè)執(zhí)行體,按幾條不同的執(zhí)行線索共同工作的情況。程序,進(jìn)程,線程,可以從不同的角度去理解。程序就是一段靜態(tài)的代碼,可以理解成一組計(jì)算機(jī)命令的集合.進(jìn)行就是這個(gè)程序一次動(dòng)態(tài)的執(zhí)行過(guò)程,從代碼的加載到執(zhí)行完畢的一個(gè)過(guò)程。線程是一個(gè)比進(jìn)程小的單位,一個(gè)進(jìn)...
多線程是Java語(yǔ)言的一大特性,多線程就是同時(shí)存在N個(gè)執(zhí)行體,按幾條不同的執(zhí)行線索共同工作的情況。程序,進(jìn)程,線程,可以從不同的角度去理解。程序就是一段靜態(tài)的代碼,可以理解成一組計(jì)算機(jī)命令的集合.進(jìn)行就是這個(gè)程序一次動(dòng)態(tài)的執(zhí)行過(guò)程,從代碼的加載到執(zhí)行完畢的一個(gè)過(guò)程。線程是一個(gè)比進(jìn)程小的單位,一個(gè)進(jìn)程再執(zhí)行的過(guò)程中可以產(chǎn)生多個(gè)線程,每個(gè)線程也是由生產(chǎn)到銷毀,可以理解成是進(jìn)行的子集。我個(gè)人用一個(gè)覺(jué)得還算恰當(dāng)?shù)谋扔鱽?lái)比喻三者。QQ客戶端就是一個(gè)程序,登陸一個(gè)QQ就是開始了這個(gè)程序的一個(gè)進(jìn)程,再Q(mào)Q上發(fā)送消息給好友就貌似這個(gè)進(jìn)程中的一個(gè)線程。不知道這樣比喻恰當(dāng)否?

  線程也是有狀態(tài)和聲明周期的,每個(gè)Java程序都會(huì)有一個(gè)缺省的主線程,對(duì)于應(yīng)用程序applcation來(lái)說(shuō)main方法就是一個(gè)主線程.Java語(yǔ)言使用的是Thread類及其子類的對(duì)象來(lái)表示線程的.創(chuàng)建一個(gè)新的線程的生命周期如下狀態(tài):

  1) 新建:當(dāng)一個(gè)Thread類或者其子類的對(duì)象被聲明并創(chuàng)建時(shí),新的線程對(duì)象處于新建狀態(tài),此時(shí)它已經(jīng)有了相應(yīng)的內(nèi)存空間和其他資源.
  2) 就緒:處于新建狀態(tài)的線程被啟動(dòng)后,將進(jìn)入線程隊(duì)列排隊(duì)等待CUP服務(wù),這個(gè)時(shí)候具備了運(yùn)行的條件,一旦輪到CPU的時(shí)候,就可以脫離創(chuàng)建它的主線程獨(dú)立開始自己的生命周期.
  3) 運(yùn)行:就緒的線程被調(diào)度并獲得CUP的處理邊進(jìn)入了運(yùn)行狀態(tài),每一個(gè)Thread類及其子類的對(duì)象都有一個(gè)重要的run()方法,當(dāng)線程對(duì)象被調(diào)度執(zhí)行的時(shí)候,它將自動(dòng)調(diào)用本對(duì)象的run()方法,從第一句代碼開始執(zhí)行。所以說(shuō)對(duì)線程的操作應(yīng)該寫到run()方法中.
  4) 阻塞:一個(gè)正在執(zhí)行的線程如果再某種情況下不能執(zhí)行了.進(jìn)入阻塞狀態(tài),這個(gè)時(shí)候它不能進(jìn)入排隊(duì)狀態(tài),只有引起了阻塞的原因消失的時(shí)候,線程才可以繼續(xù)進(jìn)入排隊(duì)狀態(tài)等待CUP處理。
  5) 死亡:處于死亡狀態(tài)的線程不具有繼續(xù)執(zhí)行的能力,線程死亡主要的原因是正常運(yùn)行的線程完成了全部工作,即執(zhí)行完了run()方法,另外就是被提前強(qiáng)制的終止了。

  線程的調(diào)度也是有優(yōu)先級(jí)別的,就是說(shuō)同樣的排列優(yōu)先級(jí)高可以提前被CPU處理,主要分三個(gè)級(jí)別,高中低.分別代表的數(shù)字是10.5.1分別有三個(gè)常量代表不可以被改變。最小優(yōu)先級(jí)的常量是MIN_PRIORITY,普通的優(yōu)先級(jí)的常量是NORM_PRIORITY,最高的優(yōu)先級(jí)的常量是MAX_PRIORITY一般主線程的優(yōu)先級(jí)是普通,另外可以通過(guò)Thread類的setPriority(int a)方法來(lái)修改系統(tǒng)自動(dòng)設(shè)置的線程優(yōu)先級(jí)。

  Java中編程實(shí)現(xiàn)多線程應(yīng)有兩種途徑,一種是創(chuàng)建自己的線程子類,另外是實(shí)現(xiàn)一個(gè)接口Runnable。無(wú)論是那種途徑最終讀需要使用Thread類及其方法。Thread類有兩種構(gòu)造方法,public Thread()用來(lái)創(chuàng)建一個(gè)線程對(duì)象。public Thread(Runnable r)創(chuàng)建線程對(duì)象,參數(shù)r成為被創(chuàng)建的目標(biāo)對(duì)象。這個(gè)目標(biāo)必須實(shí)現(xiàn)Runnbale接口,給出該接口的run()方法的方法體,再方法體中操作.用兩個(gè)構(gòu)造方法創(chuàng)建完的線程就是一個(gè)新建的狀態(tài),等待處理.然后啟動(dòng)線程的start()方法,啟動(dòng)線程對(duì)象,線程進(jìn)入排隊(duì)狀態(tài)也就是就緒狀態(tài).然后線程操作run()方法這個(gè)方法里的內(nèi)容是被系統(tǒng)處理的內(nèi)容.如果想使線程進(jìn)入休眠狀態(tài)可以調(diào)用sleep()方法,可以給一個(gè)參數(shù),代表休眠的毫秒.如果給兩個(gè)參數(shù)代表那秒。終止線程用yield()方法來(lái)完成.判斷線程是否銷毀可以用idAlive()方法判斷線程是否活著。Runnable接口只有一個(gè)方法run()方法,我們實(shí)現(xiàn)這個(gè)接口把要操作的代碼寫到這個(gè)方法中,然后再把實(shí)現(xiàn)了整個(gè)接口的類的實(shí)例傳給Therad類的構(gòu)造方法即可操作線程。

  線程同步是一個(gè)再處理線程的時(shí)候需要注意的問(wèn)題,同步方法要用synchronized關(guān)鍵字類修飾,被這個(gè)關(guān)鍵字修飾后,當(dāng)一個(gè)線程A使用這個(gè)方法后,其它線程想使用這個(gè)方法就必須等待,知道線程A使用完該方法后方可使用.下面我寫一個(gè)例子來(lái)說(shuō)明線程同步,這個(gè)例子有兩個(gè)線程會(huì)計(jì)和出納,他們共同有一個(gè)賬本.他們倆都可以存取方法對(duì)賬本進(jìn)行訪問(wèn),會(huì)計(jì)使用存取方法的時(shí)候?qū)懭氪驽X的記錄,出納則寫入取錢的記錄。因此會(huì)計(jì)使用賬本的時(shí)候出納被禁止使用,反之也是如此。就是一個(gè)人使用另外一個(gè)人必須等待。下面我通過(guò)一個(gè)小程序Applet來(lái)實(shí)現(xiàn)這個(gè)事:

  import Java.applet.*;
  import Java.awt.*;
  import Java.awt.event.*;

  public class MyThread extends Applet implements Runnable {
  int money = 100;
  TextArea text1 = null;
  TextArea text2 = null;
  Thread Kuaiji = null;
  Thread Chuna = null;

  public void init() {
  Kuaiji = new Thread(this);
  Chuna = new Thread(this);
  text1 = new TextArea(20,8);
  text2 = new TextArea(20,8);
  add(text1);
  add(text2);
  }

  public void start() {
  Kuaiji.start();
  Chuna.start();
  }

  public synchronized void Cunqu(int number) {
  if(Thread.currentThread() == Kuaiji) {
   for(int i=1;i <=3;i++) {="">
    money = money + number;
    try {Thread.sleep(1000);}
    catch(Exception e){}
    text1.append("\n"+money);
   }
  }
  else if(Thread.currentThread() == Chuna) {
   for(int i=1;i <=2;i++) {="">
    money = money - number/2;
    try {Thread.sleep(1000);}
    catch(Exception e){}
    text2.append("\n"+money);
   }
  }
  }

  public void run() {
  if(Thread.currentThread()==Kuaiji Thread.currentThread()==Chuna) {
   for(int i=1;i <=3;i++) {="">
    Cunqu(30);
   }
  }
  }
  }

  當(dāng)一個(gè)線程使用同步方法中的某個(gè)變量,而此變量又需要其他線程修改后才能符合本線程的需要,那么可以再同步方法中使用wait()方法,使本線程等待,并允許其他線程使用這個(gè)同步方法.用notfyAll()方法同志所有的由于使用這個(gè)同步方法的處于等待的線程結(jié)束等待進(jìn)入同步方法中運(yùn)行,如果使使用notfy()就是單獨(dú)同志一個(gè)線程進(jìn)行同步方法進(jìn)行活動(dòng).簡(jiǎn)單的理解就是wait()方法讓線程等待,notfy()當(dāng)一個(gè)線程運(yùn)行,notfyAll()讓全部線程運(yùn)行。雖然Java支持多線程.一般線程不需要我們自己處理.但是也是需要了解和掌握的。再日后的項(xiàng)目中獲取會(huì)根據(jù)不同情況,有不同的需求。