多線程2019-08-19

目的:多線程是知識體系中一重要的部分虱歪,使用多線程能同步完成多個(gè)任務(wù)蜂绎,提高資源使用效率進(jìn)而提高系統(tǒng)的效率。

線程所需掌握知識點(diǎn):

  • 1.如何創(chuàng)建一個(gè)線程 Thead Runnable
  • 2.線程的同步
  • 3.主線程與子線程之間使用接口回調(diào)數(shù)據(jù)
  • 4.線程之間的通信 :
    synchronized (wait notify notifyALL)

ReentrantLock lock;
Condition c = lock.newCondition()
await single singleALL

技術(shù):

1.基本知識點(diǎn):

(1)進(jìn)程和線程

進(jìn)程:正在運(yùn)行的一個(gè)程序QQ IDE 瀏覽器
系統(tǒng)會(huì)為這個(gè)進(jìn)程分配獨(dú)立的內(nèi)存資源
線程:具體執(zhí)行任務(wù)的最小單位
一個(gè)進(jìn)程最少擁有一個(gè)線程(主線程 運(yùn)行起來就執(zhí)行的線程)
線程之間是共享內(nèi)存資源的(進(jìn)程申請的)
線程之間可以通信(數(shù)據(jù)傳遞:多數(shù)情況下為主線程和子線程)
每一個(gè)線程都有自己的回路(生命周期)

(2)線程的生命周期 狀態(tài)
6441157D1DFF7B3DA414078385811477.jpg
     NEW:新建 線程剛被創(chuàng)建好
     RUNNABLE: runnable 就緒狀態(tài) 只要搶到時(shí)間片就可以運(yùn)行這個(gè)線程
     BLOCKED :阻塞狀態(tài)  sleep
     WAITING :等待     wait
     TIMED_WAITING
     TERMINATED :終止
(3)為什么需要?jiǎng)?chuàng)建子線程

如果在主線程中存在比較耗時(shí)的操作:下載視頻 上傳文件 數(shù)據(jù)處理
這些操作會(huì)阻塞主線程 后面的任務(wù)必須等這些任務(wù)執(zhí)行完畢
之后才能執(zhí)行笋鄙,用戶體驗(yàn)感差
為了不阻塞主線程师枣,需要將耗時(shí)的任務(wù)放在子線程里面去執(zhí)行

2.如何創(chuàng)建子線程:

(1)寫一個(gè)類繼承于Thread 實(shí)現(xiàn)run方法
  • join: 讓當(dāng)前這個(gè)線程阻塞,讓join的線程執(zhí)行完畢再執(zhí)行
  • setName:設(shè)置線程名稱
  • getName:獲取線程名稱
  • currentThread:獲取當(dāng)前線程的線程對象
  • start:開啟任務(wù)
    eg:
class TextTHread extends Thread{
    //實(shí)現(xiàn)run方法
    //方法里面就是具體需要執(zhí)行的代碼
    @Override
    public void run(){
        String name = Thread.currentThread().getName();
        for (int i = 0; i < 100; i++) {
            System.out.println(name+":"+(i+1));
           
        }
        super.run();
    }
}

創(chuàng)建線程:

 //main方法里面執(zhí)行的代碼 是在主線程里面執(zhí)行的
        //主線程的名稱是main (不是main方法)
        //System.out.println(Thread.currentThread().getName());

        //創(chuàng)建Thread對象
        TextTHread textTHread1 = new TextTHread();
        //設(shè)置線程名稱
        textTHread1.setName("子線程1");
        //開啟任務(wù)
        textTHread1.start();

        textTHread2 = new TextTHread();
        //設(shè)置線程名稱
        textTHread2.setName("子線程2");
        //開啟任務(wù)
        textTHread2.start();
(2).實(shí)現(xiàn)Runnable接口 實(shí)現(xiàn)run方法
  • a.創(chuàng)建任務(wù) 創(chuàng)建類實(shí)現(xiàn)Runnable接口
  • b.使用Thread 為這個(gè)任務(wù)分配線程
  • c.開啟任務(wù) start
    eg:
class PXDThread implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <=100; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}

調(diào)用方法1:

//2.1
        PXDThread pt = new PXDThread();
        //使用Thread操作這個(gè)任務(wù)
        Thread t = new Thread(pt);

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

        Thread t2 = new Thread(pt);//一個(gè)任務(wù)可以由多個(gè)線程完成啊
        t2.setName("子線程2:");
        t2.start();

調(diào)用方法2:

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

調(diào)用方法3:

//2.3
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <=100; i++) {
                    System.out.println(Thread.currentThread().getName()+i);
                }
            }
        }).start();

調(diào)用方法4:

 //2.4
        //使用Lambda表達(dá)式
        //不建議 閱讀性太差
        new Thread( () -> {
            for (int i = 1; i <=100; i++) {
                System.out.println(Thread.currentThread().getName() + i);
            }
        }).start();

3.線程安全:同步

    線程安全  synchronized Lock  加鎖解鎖
    synchronized 需要同步監(jiān)聽器 需要一把鎖
    任何對象都有一個(gè)把鎖
    如果多個(gè)線程操作同一一個(gè)代碼塊萧落,并且需要同步
    那么就需要操作同一個(gè)對象/同一個(gè)對象的同一把鎖
    synchronized(監(jiān)聽器/對象/鎖)

eg:火車票賣票 全國的賣票系統(tǒng)就一個(gè)

(1)synchronized:

synchronized(監(jiān)聽器/對象/鎖)
1.同步代碼塊
synchronized(監(jiān)聽器/對象/鎖){
需要同步的代碼
}

//用于賣票的任務(wù)
class Ticket implements Runnable{
    //定義所有車票的數(shù)量
    public static  int num = 100;
    String name;
    public Ticket(String name){
        this.name = name;
    }
    static final Object obj =new Object();

    //創(chuàng)建一個(gè)可重新載入的鎖
    static ReentrantLock lock = new ReentrantLock();

    public void run() {
        for(int i =1;i<=100;i++){
            //判斷有沒有票
            synchronized (obj){
                //需要同步的代碼
                if (num>0){
                    System.out.println(name+"出票:"+(101-num));
                    num--;
                    try {
                        //當(dāng)前線程等待
                        obj.notify();
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    break;
                }
            }

        }
    }
}
(2)Lock:

2.同步方法 同步監(jiān)聽器就是當(dāng)前對象本身
必須保證多個(gè)對象調(diào)用的同步方法時(shí)操作的統(tǒng)一對象
public synchronized void text(){
本質(zhì)就是同步代碼塊
等價(jià)于
synchronized(this) {
text()践美;
}

以下代碼中未實(shí)現(xiàn)await single singleALL等線程狀態(tài)轉(zhuǎn)換方法

//用于賣票的任務(wù)
class Ticket implements Runnable{
    //定義所有車票的數(shù)量
    public static  int num = 100;
    String name;
    public Ticket(String name){
        this.name = name;
    }
    static final Object obj =new Object();

    //創(chuàng)建一個(gè)可重新載入的鎖
    static ReentrantLock lock = new ReentrantLock();

    Condition condition = lock.newCondition();
    public void run() {
        for(int i =1;i<=100;i++){
            //判斷有沒有票
//            synchronized (obj){
//                //需要同步的代碼
            //加鎖
            lock.lock();
                if (num>0){
                    System.out.println(name+"出票:"+(101-num));
                    num--;
                    lock.newCondition();
                }else{
                    break;
                }
            //解鎖
            lock.unlock();
        }
    }
}

調(diào)用:

//        火車票賣票
//        全國的賣票系統(tǒng)就一個(gè)
        Ticket ticketCQ = new Ticket("重慶");
        Thread t1 = new Thread(ticketCQ);
        t1.start();

        Ticket ticketSH = new Ticket("上海");
        Thread t2 = new Thread(ticketSH);
        t2.start();

運(yùn)行結(jié)果太長洗贰,不予展現(xiàn)。

4.使用接口實(shí)現(xiàn)線程之間數(shù)據(jù)回調(diào)

(1)定義線程里面 Agent類
public class Agent extends Thread{
    AgentInterface target;

    @Override
    public void run() {
        System.out.println("開始找房子");
        System.out.println("---------");
        System.out.println("房子找到了 即將返回?cái)?shù)據(jù)");

        target.callBack("房子在XXX");
        super.run();
    }

    public interface AgentInterface{
        void callBack(String desc);
    }

}
(2)定義Person類:
public class Person implements Agent.AgentInterface {


    public void needHouse(){

        Agent xw = new Agent();
        xw.target = this;   //表明返回?cái)?shù)據(jù)給調(diào)用者
        xw.start();
    }

    @Override
    public void callBack(String desc) {
        System.out.println("我是小王拨脉,接受到你的數(shù)據(jù)"+desc);
    }
}
(3)調(diào)用:
 Person person = new Person();
        person.needHouse();
運(yùn)行結(jié)果:
開始找房子
---------
房子找到了 即將返回?cái)?shù)據(jù)
我是小王哆姻,接受到你的數(shù)據(jù)房子在XXX

Process finished with exit code 0

心得:

java的學(xué)習(xí)要接近尾聲了,我越來越認(rèn)識到自己前面的知識點(diǎn)有些力不從心玫膀,比如代理設(shè)計(jì)模式矛缨,哎,得好好去復(fù)習(xí)了帖旨。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末箕昭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子解阅,更是在濱河造成了極大的恐慌落竹,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件货抄,死亡現(xiàn)場離奇詭異述召,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來风喇,“玉大人,你說我怎么就攤上這事夺刑。” “怎么了分别?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵遍愿,是天一觀的道長。 經(jīng)常有香客問我耘斩,道長沼填,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任煌往,我火速辦了婚禮倾哺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刽脖。我一直安慰自己羞海,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布曲管。 她就那樣靜靜地躺著却邓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪院水。 梳的紋絲不亂的頭發(fā)上腊徙,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天简十,我揣著相機(jī)與錄音,去河邊找鬼撬腾。 笑死螟蝙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的民傻。 我是一名探鬼主播胰默,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼漓踢!你這毒婦竟也來了牵署?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤喧半,失蹤者是張志新(化名)和其女友劉穎奴迅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挺据,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡取具,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扁耐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片者填。...
    茶點(diǎn)故事閱讀 39,769評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖做葵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情心墅,我是刑警寧澤酿矢,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站怎燥,受9級特大地震影響瘫筐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铐姚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一策肝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隐绵,春花似錦之众、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至峭跳,卻和暖如春膘婶,著一層夾襖步出監(jiān)牢的瞬間缺前,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工悬襟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衅码,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓脊岳,卻偏偏與公主長得像逝段,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子逸绎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評論 2 354

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