Java實(shí)戰(zhàn)開發(fā)篇-11 多線程

多線程

一、多線程中的幾個(gè)概念

1.程序:靜態(tài)的代碼
2.進(jìn)程:正在運(yùn)行的一個(gè)程序 正在使用的QQ捶牢,Android Studio。進(jìn)程用于管理所有的資源,不進(jìn)行實(shí)際的任務(wù)
3.線程:完成具體任務(wù)沽损,QQ運(yùn)行起來就是線程(一個(gè)進(jìn)程里面可以有多個(gè)線程)。運(yùn)行QQ循头,聊天绵估、視頻炎疆、QQ游戲同時(shí)運(yùn)行,這就是一個(gè)個(gè)線程
4.主線程:Java里面国裳,main方法里面的代碼就在主線程中運(yùn)行形入。在手機(jī)里面,我們看到的主界面缝左,就是一個(gè)主線程
5.子線程:除了主線程之外的線程

二亿遂、為什么使用多線程

在主線程里面,任務(wù)的執(zhí)行是從上至下的渺杉,如果其中一個(gè)任務(wù)需要耗費(fèi)大量時(shí)間蛇数。那么這個(gè)任務(wù)后面的任務(wù)就必須等這個(gè)任務(wù)結(jié)束后才能被執(zhí)行,就會形成阻塞少办。這個(gè)時(shí)候就需要將這個(gè)任務(wù)放在另一個(gè)線程里面去執(zhí)行(子線程)
*注:不管是主線程還是子線程都有自己獨(dú)立的執(zhí)行路徑

三苞慢、如何開啟一個(gè)線程

1.寫一個(gè)類繼承于Thread

步驟:
(1)創(chuàng)建類繼承于Thread,具體執(zhí)行的任務(wù)放在run()里面
(2)創(chuàng)建類的對象
(3)調(diào)用start()方法執(zhí)行
注*線程的執(zhí)行是通過搶占時(shí)間片來獲取執(zhí)行機(jī)會的英妓,時(shí)間片是由操作系統(tǒng)來分配的
所以有多個(gè)線程的時(shí)候,每次執(zhí)行的結(jié)果可能不一樣

class TestThread extends Thread{
    //1.創(chuàng)建一個(gè)類繼承于Thread
    //可以通過重寫構(gòu)造方法給子線程命名
    public TestThread(@NonNull String name) {
        super(name);
    }
    @Override
    //子類必須實(shí)現(xiàn)父類的run方法绍赛,這個(gè)線程執(zhí)行的任務(wù)在run方法里面
    public void run() {
        System.out.println(getName());
        //也可以用Thread.currentThread()蔓纠,獲取當(dāng)前線程的名字
        System.out.println("Hello World");
    }
}
public class MyClass {
    public static void main(String[] args){
         //2.創(chuàng)建具體的對象
        TestThread testThread = new TestThread("子線程");//給子線程命名
        //3.啟動線程,不調(diào)用start無法啟動線程
        testThread.start();
}
}
    public static void testRunnable(){
        //2.創(chuàng)建具體對象
        TestRunnable testRunnable = new TestRunnable();
        //3.創(chuàng)建一個(gè)Thread對象 讓這個(gè)線程去執(zhí)行testRunnable的任務(wù)
        Thread thread = new Thread(testRunnable);
        thread.start();
    }
}

2.寫一個(gè)類實(shí)現(xiàn)Runnable接口

步驟:
(1)創(chuàng)建一個(gè)類實(shí)現(xiàn)Runnable接口,但它并不能分配線程
(2)創(chuàng)建一個(gè)該類的對象
(3)創(chuàng)建Thread類的對象來創(chuàng)建線程
(4)調(diào)用start方法開啟線程

class TestRunnable implements Runnable{
    //1.創(chuàng)建一個(gè)類實(shí)現(xiàn)Runnable方法
    //這個(gè)類不能開啟線程吗蚌,也需要通過Thread來開啟
    @Override
    public void run() {
        System.out.println("Hello World");
    }
}
public class MyClass {
    public static void main(String[] args){
        //2.創(chuàng)建具體對象
        TestRunnable testRunnable = new TestRunnable();
        //3.創(chuàng)建一個(gè)Thread對象 讓這個(gè)線程去執(zhí)行testRunnable的任務(wù)
        Thread thread = new Thread(testRunnable);
        thread.start();
}
}

3.兩種啟動方式的對比

第一種創(chuàng)建方法簡單一些腿倚,但是無法實(shí)現(xiàn)多繼承
第二種靈活性更強(qiáng),因?yàn)榻涌诳梢詫?shí)現(xiàn)多繼承

四蚯妇、線程的生命周期

線程的5種形態(tài)

new創(chuàng)建狀態(tài)->start就緒狀態(tài)-><-搶到時(shí)間片,運(yùn)行狀態(tài)(失去時(shí)間片進(jìn)入就緒狀態(tài))->run死亡狀態(tài)
運(yùn)行狀態(tài)中敷燎,可能遇到阻塞狀態(tài)

1.創(chuàng)建狀態(tài)

new Thread()

2.就緒狀態(tài)

(1)調(diào)用start()
(2)阻塞條件結(jié)束
(3)正在運(yùn)行的線程時(shí)間片被其他線程所搶奪

3.運(yùn)行狀態(tài)

從就緒狀態(tài)到運(yùn)行狀態(tài)是由操作系統(tǒng)進(jìn)行,外部無法干預(yù)

4.死亡狀態(tài)

(1)run方法結(jié)束
(2)手動讓線程暫停 stop(不建議使用箩言,通過其他方式暫停)

5.阻塞狀態(tài)

阻塞狀態(tài)分為3種硬贯,同步阻塞synchronized,等待阻塞wait陨收,其他阻塞sleep饭豹,join

五、如何讓一個(gè)線程結(jié)束

(1)使用stop()方法;(此方法不建議使用)
(2)寫一個(gè)變量來標(biāo)識線程結(jié)束

class TestThread extends Thread{
    boolean stop = true;
    @Override
   public void run() {
        while (stop) {
   System.out.println("子線程");
    }
    }
   public void terminated(){
        stop = false;
        }//寫一個(gè)終止方法
}
public class MyClass {
    public static void main(String[] args){
    TestThread t = new TestThread();
    t.start();
    for(int i = 0;i<20;i++){
        if(i==10){
            t.terminated();
    }
    }
}
}

六务漩、線程禮讓和線程插隊(duì)

線程禮讓:yield()
線程插隊(duì):join()
禮讓的線程會直接進(jìn)入就緒狀態(tài)拄衰,如果這個(gè)線程再次獲得時(shí)間片,它還會執(zhí)行饵骨,所以可能禮讓失敗

TestRunnable testRunnable = new TestRunnable();
    Thread t1 = new Thread(testRunnable,"子線程1");
     t1.start();
     for(int i = 0;i<100;i++){
     System.out.println("主線程");
     if(i == 20){
     Thread.yield();
  }
  }
public class MyClass {
    public static void main(String[] args){
    TestThread t = new TestThread();
    t.start();
}
}

插隊(duì)同理翘悉,插隊(duì)后的線程執(zhí)行完后再執(zhí)行原線程

七、多線程的利弊

1.優(yōu)點(diǎn)

(1)提高執(zhí)行的效率
(2)不會阻塞主線程

2.缺點(diǎn)

(1)多個(gè)線程操作同一個(gè)資源時(shí)居触,有可能會出錯(cuò)

class BuyTickets extends Thread{
  static int total = 10;
    @Override
    public void run() {
       for(int i = 1;i<11;i++){
       if (total == 0) {
       stop();
    }
    }
       total--;
       System.out.println("第"+(10-total)+"張票購成功");
    }
    }
}
public class MyClass {
    public static void main(String[] args){
       BuyTickets Passenger1 = new BuyTickets();
       BuyTickets Passenger2 = new BuyTickets();
       BuyTickets Passenger3 = new BuyTickets();
       Passenger1.start();
       Passenger2.start();
       Passenger3.start();
    }
}

3.克服缺點(diǎn)的辦法

(1)Lock鎖妖混,代碼塊必須使用同一把鎖
(2)2.synchronized鎖

class BuyTickets extends Thread{
    Object object = new Object();//創(chuàng)建一個(gè)臨時(shí)對象
  static int total = 10;
    @Override
    public void run() {
      for(int i = 1;i<11;i++){
      synchronized (object) {
      if (total == 0) {
      stop();
    }
    }
      total--;
      System.out.println("第"+(10-total)+"張票購成功");
    }
    }
}
public class MyClass {
    public static void main(String[] args){
       BuyTickets Passenger1 = new BuyTickets();
       BuyTickets Passenger2 = new BuyTickets();
       BuyTickets Passenger3 = new BuyTickets();
       Passenger1.start();
       Passenger2.start();
       Passenger3.start();
    }
}

*注:鎖的對象必須相同包吝,每一個(gè)對象都維護(hù)一把鎖
不管是鎖代碼塊還是鎖方法,盡量讓鎖的范圍變小

八源葫、線程間的通信

1.實(shí)現(xiàn)線程間通信的三個(gè)方法

(1)wait()讓某個(gè)線程等待
(2)notify()喚醒某個(gè)線程
(3)notifyAll()喚醒所有線程
*注:這三個(gè)方法必須由同步監(jiān)視器(必須被Lock或synchronized包裝的代碼塊)來調(diào)用

public class MyClass {
    static intersection section = new intersection();
    public static void main(String[] args){
        new Thread(new Runnable() {
            @Override
            public void run() {
                section.printnum();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                section.printlet();
            }
        }).start();
    }
}//匿名對象和匿名內(nèi)部類快速創(chuàng)建對象和調(diào)用方法
class intersection{
    int number = 1;
    char letter = 'a';
    int state = 1;//通過變化state的值來改變線程
    public synchronized void printnum(){
    while(true){
       if(state != 1){
       try {
       this.wait();
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  }
    System.out.println(number);
    number++;
      if(number == 27){
      break;
  }
      state = 2;
      this.notify();
  }
  }
  public synchronized void printlet(){
        while(true){
        if(state != 2){
        try {
        this.wait();
   } catch (InterruptedException e) {
     e.printStackTrace();
   }
   }
    System.out.println(letter);
    letter++;
     if(letter == ('z'+1)){
     break;
    }
     state = 1;
     this.notify();
    }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诗越,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子息堂,更是在濱河造成了極大的恐慌嚷狞,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荣堰,死亡現(xiàn)場離奇詭異床未,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)振坚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門薇搁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渡八,你說我怎么就攤上這事啃洋。” “怎么了屎鳍?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵宏娄,是天一觀的道長。 經(jīng)常有香客問我逮壁,道長孵坚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任窥淆,我火速辦了婚禮卖宠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忧饭。我一直安慰自己扛伍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布眷昆。 她就那樣靜靜地躺著蜒秤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亚斋。 梳的紋絲不亂的頭發(fā)上作媚,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音帅刊,去河邊找鬼纸泡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赖瞒,可吹牛的內(nèi)容都是我干的女揭。 我是一名探鬼主播蚤假,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吧兔!你這毒婦竟也來了磷仰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤境蔼,失蹤者是張志新(化名)和其女友劉穎灶平,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箍土,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逢享,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吴藻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞒爬。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沟堡,靈堂內(nèi)的尸體忽然破棺而出侧但,到底是詐尸還是另有隱情,我是刑警寧澤弦叶,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布俊犯,位于F島的核電站,受9級特大地震影響伤哺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜者祖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一立莉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧七问,春花似錦蜓耻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至讥耗,卻和暖如春有勾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背古程。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工蔼卡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挣磨。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓雇逞,卻偏偏與公主長得像荤懂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子塘砸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容