Java之多線程

知識(shí)點(diǎn)
  • 進(jìn)程:正在運(yùn)行的某個(gè)程序 如:QQ 瀏覽器
    系統(tǒng)會(huì)為這個(gè)進(jìn)程分配獨(dú)立的內(nèi)存資源
  • 線程:具體執(zhí)行任務(wù)的最小單位
    一個(gè)進(jìn)程最少擁有一個(gè)線程(主線程 運(yùn)行起來就執(zhí)行的線程)
    線程之間是共享一片內(nèi)存空間(進(jìn)程申請(qǐng))
    線程之間可以通信 (數(shù)據(jù)傳遞:多數(shù)為主線程和子線程)
    每一個(gè)線程都有自己的運(yùn)行回路(生命周期)
  • 線程的生命周期 狀態(tài)
    New:新建 線程剛被創(chuàng)建
    RUNNABLE:就緒狀態(tài)(準(zhǔn)備好了章姓,隨時(shí)可以運(yùn)行)只要搶到時(shí)間片就可以運(yùn)行
    BLOCKED:阻塞狀態(tài) (時(shí)間片結(jié)束 sleep wait)
    WAITING:等待 wait
    TIMED_WAITING
    TERMINATED
  • 為什么需要?jiǎng)?chuàng)建一個(gè)子線程
    如果在主線程中存在比較耗時(shí)的操作 如:下載視頻凫乖,上傳文件虫埂,數(shù)據(jù)處理
    這些操作會(huì)阻塞主線程春寿,后面的任務(wù)必須等這些任務(wù)執(zhí)行完畢捏卓,之后才能執(zhí)行堕虹,用戶體驗(yàn)比較差
    為了不阻塞主線程猪落,需要將耗時(shí)的任務(wù)放在子線程中去處理
  • 線程阻塞的原理


    2M``N0O_9774F1D0TJ)Z@X6.png
內(nèi)容梗概

-1. 如何創(chuàng)建一個(gè)(子)線程
-2.線程的同步
-3.主線程和子線程之間使用數(shù)據(jù)回調(diào)
-4.兩個(gè)線程交替執(zhí)行
-5.線程間的通信

主要內(nèi)容
-1.如何創(chuàng)建一個(gè)(子)線程
  • 寫一個(gè)類繼承于Thread,實(shí)現(xiàn)run方法
  public class MyClass{
      static TestThread1 tt2;
      public static void main(String[] args){
          // 創(chuàng)建Thread的對(duì)象
        TestThread1 tt=new TestThread1();
        // 設(shè)置線程的名稱
       tt.setName("子線程1");
       // 開啟任務(wù)
       tt.start();
       }
  }
  class TestThread1 extends Thread{
  //實(shí)現(xiàn)run方法

  @Override
  public void run() {
    //run方法里就是具體需要執(zhí)行的代碼
    String name=Thread.currentThread().getName();
    for (int i = 1; i <= 100; i++) {
        System.out.println(name+":"+i);
    }
    super.run();
    }
  }

注:不能同時(shí)開啟同一個(gè)線程,會(huì)出錯(cuò)

  TestThread1 tt=new TestThread1();
  tt.setName("子線程1");
  tt.start();
  TestThread1 tt2;
  tt2=new TestThread1();
  tt2.setName("子線程2");
  tt2.start();
  • 實(shí)現(xiàn)Runnable接口,實(shí)現(xiàn)run方法
    (1)創(chuàng)建任務(wù):創(chuàng)建類實(shí)現(xiàn)Runnable接口
    (2)使用Thread,為這個(gè)任務(wù)分配線程
    (3)開啟任務(wù),start()

有四種使用方法蹬刷,先創(chuàng)建一個(gè)類

  class ZRThread implements Runnable{
  @Override
  public void run() {
      for (int i = 1;  i< 100; i++) {
          System.out.println(Thread.currentThread().getName()+": "+i);
      }
    }
  }

第一種方法:

    //步驟1:創(chuàng)建一個(gè)任務(wù):創(chuàng)建一個(gè)類實(shí)現(xiàn)Runnable接口
    ZRThread zt=new ZRThread();
    //步驟2:使用Thread操作這個(gè)任務(wù)
    Thread t=new Thread(zt);
    t.setName("子線程1");
    t.start();
    Thread t2=new Thread(zt);
    t2.setName("子線程2");
    t2.start();

第二種方法:

  //這個(gè)任務(wù)只需使用一次
    Thread t=new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1;  i< 100; i++) {
        System.out.println(Thread.currentThread().getName()+": "+i);
    }

        }
    });
    t.setName("子線程1");
    t.start();

第三種方法:

    //創(chuàng)建線程的同時(shí) 直接開啟線程
    //不需要操作線程對(duì)象本身
    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1;  i< 100; i++) {
                System.out.println(Thread.currentThread().getName()+": "+i);
            }
        }
    }).start();

第四種方法:

  //使用Lambda表達(dá)式瓢捉,但閱讀性太差
    new Thread(()->{
        for (int i = 1;  i< 100; i++) {
            System.out.println(Thread.currentThread().getName()+": "+i);
        }
    }).start();
-2.線程的同步
  • 線程安全
    多個(gè)線程操作同一個(gè)資源,線程無法確定自己什么時(shí)候被阻塞办成,容易導(dǎo)致數(shù)據(jù)錯(cuò)誤
  • 同步代碼塊
    synchronized (監(jiān)聽器/對(duì)象/鎖){
    需要同步的代碼
    }
  public class MyClass {
  public static void main(String[] args){
  Ticket ticketCQ=new Ticket("重慶");
  Thread t1=new Thread(ticketCQ);
  t1.start();
      }
  }
  class Ticket implements Runnable{
  //定義所有車票的數(shù)量
  public static int num=100;
  String name;
  public Ticket(String name){
      this.name=name;
  }
  // static實(shí)現(xiàn)同步(代碼塊)
  static final Object obj=new Object();
  @Override
  public void run() {
    for (int i = 1; i <= 100; i++) {
        synchronized (obj) {
            //需要同步的代碼
            //判斷有沒有票
            if (num > 0) {
                System.out.println(name + "出票: " + num);
                num--;
            } else {
                break;
            }
          }
       }
    }
 }
  • 同步方法 同步監(jiān)聽器是同一個(gè)對(duì)象
    必須確保對(duì)象調(diào)用的同步操作時(shí)操作的統(tǒng)一對(duì)象
    public synchronized void test() {
    }
    本質(zhì)都是同步代碼塊
    等價(jià)于
    synchronized (this){
    }
  class Ticket implements Runnable {
  public static int num = 100;
  String name;

  public Ticket(String name) {
      this.name = name;
  }
  static final Object obj = new Object();
  @Override
   public void run() {
      test();
   }

  public synchronized void test() {
    for (int i = 1; i <= 100; i++) {
        //需要同步的代碼
        //判斷有沒有票
        if (num > 0) {
            System.out.println(name + "出票: " + num);
            num--;
        } else {
            break;
         }
      }
   }
}
-3.主線程和子線程之間使用數(shù)據(jù)回調(diào)
  public class MyClass {
  public static void main(String[] args){
  Person zs=new Person();
    zs.needHouse();
  }
}
class ZRThread implements Runnable{
@Override
public void run() {
    for (int i = 1;  i< 100; i++) {
        System.out.println(Thread.currentThread().getName()+": "+i);
        }
    }
}

分別定義兩個(gè)類泡态,在主函數(shù)中實(shí)現(xiàn)回調(diào)

  public class Person implements Agent.AgentInterface {
  public void needHouse(){
      Agent xw=new Agent();
      xw.target=this;
      xw.start();
  }

  @Override
  public void callBack(String desc) {
      System.out.println("我是小王,接收到你的數(shù)據(jù)了:"+desc);
      }
  }
   public class Agent extends Thread{
   AgentInterface target;
   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
       System.out.println("開始找房子");
       System.out.println("—————————");
       System.out.println("房子找到了诈火,即將返回?cái)?shù)據(jù)");
       target.callBack("房子在西南大學(xué)");
       super.run();
   }
   public interface AgentInterface{
       void callBack(String desc);
       }
   }
-4.兩個(gè)線程交替執(zhí)行
  public class MyClass {
  public static void main(String[] args){
  Ticket ticketCQ=new Ticket("重慶");
    Thread t1=new Thread(ticketCQ);
    t1.start();
    Ticket ticketSH=new Ticket("上海");
    Thread t2=new Thread(ticketSH);
    t2.start();
    }
  }
  class Ticket implements Runnable{
  public static int num=100;
  String name;
  public Ticket(String name){
      this.name=name;
  }
  static final Object obj=new Object();
  static ReentrantLock lock=new ReentrantLock();
  @Override
  public void run() {
    for (int i = 1; i <= 100; i++) {
        synchronized (obj) {
            //需要同步的代碼
            //判斷有沒有票
            if (num > 0) {
                System.out.println(name + "出票: " + num);
                num--;
                try {
                    //通知其他線程執(zhí)行
                    obj.notify();
                    //當(dāng)前線程等待
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                break;
            }
          }
        }
     }
  }
-5.線程間的通信

-使用ReentrantLock同步

  class Ticket implements Runnable{
  //定義所有車票的數(shù)量
  public static int num=100;
  String name;
  public Ticket(String name){
      this.name=name;
  }
  // static實(shí)現(xiàn)同步(代碼塊)
  //創(chuàng)建一個(gè)可重入的鎖
  static ReentrantLock lock=new ReentrantLock();
  @Override
  public void run() {
      for (int i = 1; i <= 100; i++) {
          //加鎖
          lock.lock();
              //需要同步的代碼
              //判斷有沒有票
              if (num > 0) {
                  System.out.println(name + "出票: " + num);
                  num--;
              } else {
                  break;
              }
          //解鎖
          lock.unlock();
      }
   }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兽赁,一起剝皮案震驚了整個(gè)濱河市状答,隨后出現(xiàn)的幾起案子冷守,更是在濱河造成了極大的恐慌,老刑警劉巖惊科,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拍摇,死亡現(xiàn)場離奇詭異,居然都是意外死亡馆截,警方通過查閱死者的電腦和手機(jī)充活,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜡娶,“玉大人混卵,你說我怎么就攤上這事〗颜牛” “怎么了幕随?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宿接。 經(jīng)常有香客問我赘淮,道長,這世上最難降的妖魔是什么睦霎? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任梢卸,我火速辦了婚禮,結(jié)果婚禮上副女,老公的妹妹穿的比我還像新娘蛤高。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布襟齿。 她就那樣靜靜地躺著姻锁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猜欺。 梳的紋絲不亂的頭發(fā)上位隶,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音开皿,去河邊找鬼涧黄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赋荆,可吹牛的內(nèi)容都是我干的笋妥。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼窄潭,長吁一口氣:“原來是場噩夢啊……” “哼春宣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嫉你,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤月帝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后幽污,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚷辅,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年距误,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了簸搞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡准潭,死狀恐怖趁俊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刑然,我是刑警寧澤寺擂,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站闰集,受9級(jí)特大地震影響沽讹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜武鲁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一爽雄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沐鼠,春花似錦挚瘟、人聲如沸叹谁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽焰檩。三九已至,卻和暖如春订框,著一層夾襖步出監(jiān)牢的瞬間析苫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工穿扳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衩侥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓矛物,卻偏偏與公主長得像茫死,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子履羞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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

  • ? 進(jìn)程峦萎、線程和多線程 進(jìn)程: 定義:進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng)。它是操作系統(tǒng)...
    默云客閱讀 255評(píng)論 0 0
  • Thread(耦合忆首,不推薦) Runnable(解耦爱榔,推薦) Executors ExecutorService ...
    如果仲有聽日閱讀 699評(píng)論 0 0
  • 開心一笑 【服務(wù)員來個(gè)西紅柿炒雞蛋,服務(wù)員:沒有西紅柿了雄卷。那來一個(gè)白菜燉豆腐搓蚪,服務(wù)員:沒有豆腐了……那好蛤售,來個(gè)雞蛋...
    阿_毅閱讀 1,832評(píng)論 0 10
  • 游麥積山石窟 王學(xué)明 那蒼然眩暈般聳立的似乎不是山丁鹉,而是經(jīng)數(shù)千年風(fēng)...
    山之尖閱讀 478評(píng)論 1 2
  • 微博上一個(gè)博主,失聯(lián)了9天悴能,回來在微博上講述了自己突發(fā)腦出血的事情揣钦。接下來,評(píng)論中開始說著“這夜漠酿,真的不能再熬了”...
    七蕭蕭閱讀 104評(píng)論 0 0