還不懂Java高并發(fā)的挠乳,建議看看這篇阿里大佬的總結(jié),寫的非常詳細(xì)

前言

進(jìn)程是計(jì)算機(jī)中程序關(guān)于某幾何數(shù)據(jù)集合上的一次運(yùn)行活動(dòng)姑躲,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位睡扬。是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)

線程可以說(shuō)是輕量級(jí)的進(jìn)程,是程序執(zhí)行的最小單位黍析,使用多線程而不用多進(jìn)程去進(jìn)行并發(fā)程序的設(shè)計(jì)卖怜,是因?yàn)榫€程之間的切換與調(diào)度的成本遠(yuǎn)小于進(jìn)程。

線程的幾種狀態(tài)

New狀態(tài)表示剛剛創(chuàng)建的線程阐枣,這種線程還沒有開始執(zhí)行
RUNNABLE:當(dāng)線程創(chuàng)建好之后马靠,調(diào)用線程的start方法就會(huì)進(jìn)入就緒狀態(tài)奄抽。
BLOCKED:當(dāng)線程運(yùn)行過(guò)程如果遇到了Syschronized就會(huì)進(jìn)入阻塞狀態(tài)。
TIMED_WATING:表示等待狀態(tài)甩鳄,有時(shí)間限制的(sleep)
WAITING:表示進(jìn)入一個(gè)無(wú)時(shí)間顯示的等待狀態(tài)(wait)
TERMINATED:表示結(jié)束狀態(tài)逞度。

線程的基本操作

新建線程

實(shí)現(xiàn)Runable接口或者new Thread

終止線程

為什么不建議使用stop?

因?yàn)閟top方法比較暴力,強(qiáng)行把執(zhí)行的程序終止妙啃,可能會(huì)引發(fā)數(shù)據(jù)不一致的問(wèn)題第晰,Thread.stop()方法在結(jié)束線程時(shí),會(huì)直接終止線程彬祖,并立即釋放這個(gè)線程的所持有的鎖茁瘦。比如數(shù)據(jù)寫到一半,強(qiáng)行終止掉了储笑,數(shù)據(jù)就會(huì)被破壞甜熔。

線程中斷

interrupt() //中斷線程。相當(dāng)于設(shè)置中斷標(biāo)志位
isInterrypted() //判斷是否被中斷
interrupted() //判斷是都被中斷突倍,并清除當(dāng)前的中斷狀態(tài)


Thread.sleep()方法由于中斷而拋出異常腔稀,此時(shí)它會(huì)清除中斷標(biāo)記,如果不加處理羽历,那么下一次循環(huán)開始時(shí)焊虏,就無(wú)法捕獲這個(gè)異常,可以再次設(shè)置中斷標(biāo)記來(lái)方便循環(huán)判斷秕磷。

等待和通知

當(dāng)在一個(gè)對(duì)象實(shí)力上條用wait()方法之后诵闭。當(dāng)前線程就會(huì)在這個(gè)對(duì)象上等待。在線程A中調(diào)用了obj.wait()方法澎嚣,那么變成A就會(huì)停止繼續(xù)執(zhí)行疏尿,轉(zhuǎn)為等待狀態(tài),直到其他線程調(diào)用了obj.notify()方法才有機(jī)會(huì)繼續(xù)執(zhí)行(并不是一定)

如果一個(gè)線程調(diào)用了obj.wait()那么它就會(huì)進(jìn)入這個(gè)object的等待隊(duì)列易桃,這個(gè)等待隊(duì)列可能會(huì)有多個(gè)線程褥琐,因?yàn)橄到y(tǒng)運(yùn)行多個(gè)線程同時(shí)等待某一個(gè)對(duì)象,當(dāng)obj.notify()方法被調(diào)用時(shí)晤郑,就會(huì)隨機(jī)選擇一個(gè)線程敌呈,將其喚醒,這個(gè)喚醒是完全隨機(jī)的造寝。

notifyAll()方法的功能是喚醒所有在該對(duì)象等待隊(duì)列中等待的線程磕洪。

守護(hù)線程的finally不一定會(huì)執(zhí)行。如果除守護(hù)線程外的所有線程都結(jié)束了匹舞,那么守護(hù)線程就立即退出沒有執(zhí)行finally代碼塊的機(jī)會(huì)褐鸥。

掛起(suspend)和繼續(xù)(resume)執(zhí)行

不推薦執(zhí)行suspend(),因?yàn)樵摲椒ㄔ趯?dǎo)致線程暫停的同時(shí)赐稽,并不會(huì)釋放任何資源叫榕。影響其他想要訪問(wèn)該資源的線程浑侥,直到當(dāng)前線程使用resume操作馒胆,是當(dāng)前線程繼續(xù)執(zhí)行卡儒,但是此處有一個(gè)隱患吧兔。如果resume在suspend之前運(yùn)行了鳍徽,那么被掛起的線程將不能繼續(xù)執(zhí)行下去。

public class BadSuspend {
    public static Object u = new Object();
    static ChangeObjectThread t1 = new ChangeObjectThread("t1");
    static ChangeObjectThread t2 = new ChangeObjectThread("t2");

    public static class ChangeObjectThread extends Thread {
        public ChangeObjectThread(String name){
            super.setName(name);
        }
        @Override
        public void run() {
            synchronized (u) {
                System.out.println("in "+getName());
                Thread.currentThread().suspend();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        t1.start();
        Thread.sleep(100);
        t2.start();
        t1.resume();
        t2.resume();//無(wú)法直到這一行先執(zhí)行傍衡,還是Thread.currentThread().suspend();先執(zhí)行
        t1.join();
        t2.join();
    }
}

等待線程結(jié)束(join)和謙讓(yeild)

public final synchronized void join(long millis) throws InterruptedException//有最大等待時(shí)長(zhǎng)的等待

public final synchronized void join(long millis, int nanos)
throws InterruptedException//毫秒词渤,加納秒級(jí)別的等待

public final void join() throws InterruptedException//表示無(wú)限期的等待

package com.atmb.me;

public class joinAndYeild {
    public volatile  static  int i =0;

    public static class myThread implements Runnable{
        @Override
        public void run() {
            for (int j = 0; j < 1000000; j++) {
                i+=1;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new myThread());
        thread.start();
        thread.join();//等待thread線程執(zhí)行結(jié)束
        System.out.println(i);//結(jié)果為1000000
    }
}

    public static native void yield();

這個(gè)方法一旦執(zhí)行猫妙,就會(huì)使當(dāng)前線程讓出cpu,讓出cpu之后尖昏,該線程會(huì)繼續(xù)進(jìn)行cpu資源的爭(zhēng)奪仰税,之后繼續(xù)正常運(yùn)行。

線程組

package com.atmb.me;

public class ThreadGroupTest implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getThreadGroup().getName()+"==="+Thread.currentThread().getName());
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ThreadGroup group1 = new ThreadGroup("group1");
        Thread thread1 = new Thread(group1, new ThreadGroupTest());
        Thread thread2 = new Thread(group1, new ThreadGroupTest());
        thread1.start();
        thread2.start();
        System.out.println(group1.activeCount());//活躍線程數(shù)
        group1.list();
    }
}
<<<
2
group1===Thread-0
java.lang.ThreadGroup[name=group1,maxpri=10]
group1===Thread-1
    Thread[Thread-0,5,group1]
    Thread[Thread-1,5,group1]

守護(hù)線程(Daemon)

守護(hù)線程要守護(hù)的對(duì)象已經(jīng)不存在了抽诉,那么整個(gè)應(yīng)用程序就應(yīng)該技術(shù)陨簇,因此當(dāng)java應(yīng)用內(nèi)只有守護(hù)線程時(shí),java虛擬機(jī)就會(huì)自然退出迹淌。

package geym.ch2;

public class DaemonDemo {
    public static class DaemonT extends Thread{
        public void run(){
            while(true){
                System.out.println("I am alive");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t=new DaemonT();
        t.setDaemon(true);
        t.start();

//        Thread.sleep(2000);
    }
}

設(shè)置守護(hù)線程河绽,必須要在start之前設(shè)置,否則會(huì)得到異常信息唉窃。

線程優(yōu)先級(jí)

Java中的線程可以有自己的優(yōu)先級(jí)耙饰。優(yōu)先級(jí)高的線程在競(jìng)爭(zhēng)資源時(shí),會(huì)更有優(yōu)勢(shì)纹份,更大概率搶占到資源苟跪,java中線程優(yōu)先級(jí)可以設(shè)置為1-10.
其中有三個(gè)靜態(tài)標(biāo)量標(biāo)識(shí)三個(gè)對(duì)應(yīng)的優(yōu)先級(jí)。

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

public class PriorityDemo {
    public static class HightPriority extends Thread{
        static int count=0;
        public void run(){
            while(true){
                synchronized(PriorityDemo.class){
                    count++;
                    if(count>10000000){
                        System.out.println("HightPriority is complete");
                        break;
                    }
                }
            }
        }
    }
    public static class LowPriority extends Thread{
        static int count=0;
        public void run(){
            while(true){
                synchronized(PriorityDemo.class){
                    count++;
                    if(count>10000000){
                        System.out.println("LowPriority is complete");
                        break;
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread high=new HightPriority();
        LowPriority low=new LowPriority();
        high.setPriority(Thread.MIN_PRIORITY);
        low.setPriority(Thread.MAX_PRIORITY);
        low.start();
        high.start();
    }
}

線程安全與關(guān)鍵字synchronized

synchronized

  • 指定加鎖對(duì)象矮嫉,對(duì)給定的對(duì)象進(jìn)行加鎖削咆,
  • 用于實(shí)例方法,對(duì)當(dāng)前的實(shí)例進(jìn)行加鎖
  • 用于靜態(tài)方法蠢笋,對(duì)當(dāng)前類進(jìn)行加鎖

錯(cuò)誤的加鎖

package com.atmb.me;

public class lockError implements Runnable {
    public static Integer i =0;
    public static lockError instance =  new lockError();

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(i);
    }

    @Override
    public void run() {
        for (int j = 0; j < 100000; j++) {
            synchronized (i){
                i+=1;
            }
        }
    }
}
<<<
142957

原因在于Integer類型屬于不可變對(duì)象,一旦創(chuàng)建就不可能被改變鳞陨,當(dāng)integer對(duì)象賦值為新值時(shí)昨寞,當(dāng)前引用指向的對(duì)象就改變了。

指令重排的前提

指令重排需要保證串行語(yǔ)義的一致性厦滤,指令重排不會(huì)使串行的語(yǔ)義邏輯發(fā)生問(wèn)題援岩。

指令重排的目的?

為了減少中斷流水線

那些指令不能重排

  • 程序順序原則掏导,一個(gè)線程內(nèi)保證語(yǔ)義的串行性
  • volatile規(guī)則:volatile變量的寫先與讀發(fā)生享怀,寶整理volatile變量的可見性
  • 傳遞性:解鎖必然發(fā)生在隨后的加鎖前
  • 線程的start()方法先于它的動(dòng)作
  • 線程的所有操作先于線程的終結(jié)(interrupt)
  • 線程的中斷(interrupt())先于被中斷線程的代碼
  • 對(duì)象的構(gòu)造函數(shù)的執(zhí)行,結(jié)束先于finalize()的方法

是否會(huì)釋放鎖

  • yield讓出cpu執(zhí)行權(quán)趟咆,不會(huì)釋放鎖

  • sleep休眠時(shí)添瓷,不會(huì)釋放鎖

  • 調(diào)用wait方法之后梅屉,會(huì)釋放鎖,喚醒之后鳞贷,會(huì)再次競(jìng)爭(zhēng)鎖坯汤,然后執(zhí)行wait()方法后的代碼

  • nofify nodifyall 對(duì)鎖沒有影響,一般放同步代碼塊的最后一行

最后

感謝你看到這里搀愧,看完有什么的不懂的可以在評(píng)論區(qū)問(wèn)我惰聂,覺得文章對(duì)你有幫助的話記得給我點(diǎn)個(gè)贊,每天都會(huì)分享java相關(guān)技術(shù)文章或行業(yè)資訊咱筛,歡迎大家關(guān)注和轉(zhuǎn)發(fā)文章搓幌!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市迅箩,隨后出現(xiàn)的幾起案子鼻种,更是在濱河造成了極大的恐慌,老刑警劉巖沙热,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叉钥,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡篙贸,警方通過(guò)查閱死者的電腦和手機(jī)投队,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)爵川,“玉大人敷鸦,你說(shuō)我怎么就攤上這事∏薰保” “怎么了扒披?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)圃泡。 經(jīng)常有香客問(wèn)我碟案,道長(zhǎng),這世上最難降的妖魔是什么颇蜡? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任价说,我火速辦了婚禮,結(jié)果婚禮上风秤,老公的妹妹穿的比我還像新娘鳖目。我一直安慰自己,他們只是感情好缤弦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布领迈。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狸捅。 梳的紋絲不亂的頭發(fā)上衷蜓,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音薪贫,去河邊找鬼恍箭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瞧省,可吹牛的內(nèi)容都是我干的扯夭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼鞍匾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼交洗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起橡淑,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤构拳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后梁棠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體置森,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年符糊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凫海。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡男娄,死狀恐怖行贪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情模闲,我是刑警寧澤建瘫,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站尸折,受9級(jí)特大地震影響啰脚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翁授,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一拣播、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧收擦,春花似錦、人聲如沸谍倦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)昼蛀。三九已至宴猾,卻和暖如春圆存,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仇哆。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工沦辙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讹剔。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓油讯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親延欠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陌兑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348