java多線程學習

第一步:細說多線程之Thread VS Runnable
https://www.imooc.com/learn/312
第二步:Java Socket應用
https://www.imooc.com/learn/161
第三步:Java高并發(fā)之魂:synchronized深度解析
https://www.imooc.com/learn/1086
第四步:Java多線程之內(nèi)存可見性
https://www.imooc.com/learn/352

一冶伞、 線程的實現(xiàn)方式

Java多線程的4種實現(xiàn)方式

  • 1.繼承Thread并重寫run方法,并調(diào)用start方法
/**
 * Java實現(xiàn)多線程的方式1
 * 繼承Thread類潘拱,重寫run方法
 */
class MyThread extends Thread {
    
    @Override
    public void run() {
        //此處為thread執(zhí)行的任務內(nèi)容
        System.out.println(Thread.currentThread().getName());
    }
}

public class Demo03 {
    
    
    public static void main(String[] args) {
        
        for(int i=0;i<2;i++) {
            Thread t = new MyThread();
            //輸出:
            //Thread-0 Thread-1
            t.start();
        }
    }
}

  • 2.實現(xiàn)Runnable接口,并用其初始化Thread瘟判,然后創(chuàng)建Thread實例锣险,并調(diào)用start方法
/**
 * Java實現(xiàn)多線程的方式2
 * 實現(xiàn)Runnable接口
 */
class MyThread implements Runnable {
    
    @Override
    public void run() {
        //此處為thread執(zhí)行的任務內(nèi)容
        System.out.println(Thread.currentThread().getName());
    }
}

public class Demo03 {
    
    
    public static void main(String[] args) {
        
        for(int i=0;i<2;i++) {
            Thread t = new Thread(new MyThread());
            //輸出:
            //Thread-0 Thread-1
            t.start();
        }
    }
}

  • 3.實現(xiàn)Callable接口,并用其初始化Thread般眉,然后創(chuàng)建Thread實例我纪,并調(diào)用start方法

/**
 * Java實現(xiàn)多線程的方式3
 * 實現(xiàn)Callable接口
 */
class MyThread implements Callable<Integer> {
    
    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName());
        return null;
    }
}

public class Demo03 {
    
    
    public static void main(String[] args) {
        
        for(int i=0;i<2;i++) {
            //創(chuàng)建MyThread實例
            Callable<Integer> c = new MyThread();
            //獲取FutureTask
            FutureTask<Integer> ft = new FutureTask<Integer>(c);
            //使用FutureTask初始化Thread
            Thread t = new Thread(ft);
            //輸出:
            //Thread-0 Thread-1
            t.start();
        }
    }
}

  • 4.使用線程池創(chuàng)建

/**
 * Java實現(xiàn)多線程的方式4
 * 線程池
 */
class MyThread implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
    
}

class MyThread2 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName());
        return 0;
    }

    
}

public class Demo03 {
    
    
    public static void main(String[] args) {
        
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for(int i=0;i<2;i++) {
            executorService.execute(new MyThread());
            FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread2());
            //輸出
//          pool-1-thread-1
//          pool-1-thread-2
//          pool-1-thread-3
//          pool-1-thread-4
            executorService.submit(ft);
        }
        executorService.shutdown();
    }
}

二慎宾、 正確啟動線程的方式

啟動線程的三種方式

  • 1)猎莲、繼承Thread類:
    • a.定義Thread類的子類惧所,并重寫該類的run()方法胸嘴,該run()方法的方法體就代表了線程
    • b. 需要完成的任務埠对。因此把run方法稱為線程執(zhí)行體。
      創(chuàng)建Thread子類的實例之宿,即創(chuàng)建了線程對象族操。
    • c.調(diào)用線程對象的start()方法來啟動該線程。
  • 2)比被、實現(xiàn)Runnable接口:
    • a.定義Runnable接口的實現(xiàn)類色难,并重寫該接口的run方法,該run方法的方法體同樣是該線程的線程執(zhí)行體

    • b.創(chuàng)建Runnable實現(xiàn)類的實例對象等缀,并以此實例對象作為Thread的target來創(chuàng)建Thread類枷莉,該Thread對象才是真正的線程對象。

    • c.調(diào)用線程對象的start()方法來啟動該線程尺迂。

  • 3)笤妙、匿名內(nèi)部類:
    匿名內(nèi)部類本質(zhì)上也是一個類實現(xiàn)了Runnable接口,重寫了run方法噪裕,只不過這個類沒有名字蹲盘,直接作為參數(shù)傳入Thread類,示例代碼:
public class Main {
    
    public static void main(String[] args) {
        new Thread(new Runnable() {
            
            public void run() {
                for (int i = 0; i < 50; i++) {
                    System.out.println(Thread.currentThread().getName() + "執(zhí)行" + i);
                }
            }
        }).start();
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName() + "執(zhí)行" + i);
        }
    }
}

三膳音、 如何停止線程

使用標志位

//定義一個標志位:cancelled召衔,cancelled為true是即run方法結(jié)束,反之繼續(xù)while里面的任務祭陷。通過cancell方法來停止任務苍凛。
  static class CancelledTaggedRunnnable implements Runnable{
        private volatile boolean cancelled = false;
        @Override
        public void run() {
            while(!cancelled){
             //沒有停止需要做什么操作
            }
            //線程停止后需要干什么
            System.out.println("任務結(jié)束了");
        }
        public void cancell(){
            cancelled = true;
        }
    }

 @Test
    public void testCancelledTaggedRunnnable() throws InterruptedException {
        CancelledTaggedRunnnable taggedRunnnable = new CancelledTaggedRunnnable();
        Thread thread = new Thread(taggedRunnnable);
        thread.start();
 
        System.err.println(thread.isAlive());
 
        Thread.sleep(1000);
        taggedRunnnable.cancell();
 
        Thread.sleep(1000);
        System.err.println(thread.isAlive());
 
        Thread.sleep(1000);
        System.err.println(thread.isAlive());
    }

強行停止

對于多線程,使用中斷策略 較為優(yōu)雅兵志,也是官方的推薦醇蝴。線程停止前你應該做一些操作,從而保證該線程運行后的數(shù)據(jù)不會被丟失想罕,這一點在多線程中極為重要悠栓。
但是對于中斷策略還是有一個很大的缺陷,那就是按价,必須通過中斷的阻塞函數(shù)惭适,如:我使用的BlockingQueue的put方法,也可以是Thread.sleep()方法俘枫,才能拋出InterruptedException腥沽。如果拋不出這樣的異常呢逮走?
對于單線程鸠蚪,還有一個簡單粗暴的方式,那就是Java已經(jīng)不再使用的Thread stop方法。
使用方法即直接調(diào)用:thread.stop()即可茅信。
如果你對該線程的操作不再關(guān)心了盾舌,對結(jié)果也不再在意了,使用該方法也是可以的蘸鲸。
但多線程情況下妖谴,或者線程帶鎖的情況下 那就要慎用了。該方法不安全

四酌摇、 如何中斷線程

現(xiàn)在我們知道了使用 stop() 方式停止線程是非常不安全的方式膝舅,那么我們應該使用什么方法來停止線程呢?答案就是使用 interrupt() 方法來中斷線程窑多。
需要明確的一點的是:interrupt() 方法并不像在 for 循環(huán)語句中使用 break 語句那樣干脆仍稀,馬上就停止循環(huán)。調(diào)用 interrupt() 方法僅僅是在當前線程中打一個停止的標記埂息,并不是真的停止線程技潘。

也就是說,線程中斷并不會立即終止線程千康,而是通知目標線程享幽,有人希望你終止。至于目標線程收到通知后會如何處理拾弃,則完全由目標線程自行決定值桩。這一點很重要,如果中斷后砸彬,線程立即無條件退出颠毙,那么我們又會遇到 stop() 方法的老問題。

public class InterruptThread1 extends Thread{

    public static void main(String[] args) {
        try {
            InterruptThread1 t = new InterruptThread1();
            t.start();
            Thread.sleep(200);
            t.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        super.run();
        for(int i = 0; i <= 200000; i++) {
            System.out.println("i=" + i);
        }
    }
}
運行結(jié)果

從輸出的結(jié)果我們會發(fā)現(xiàn) interrupt 方法并沒有停止線程 t 中的處理邏輯砂碉,也就是說即使 t 線程被設(shè)置為了中斷狀態(tài)蛀蜜,但是這個中斷并不會起作用,那么該如何停止線程呢增蹭?
這就需要使用到另外兩個與線程中斷有關(guān)的方法了:

public boolean Thread.isInterrupted() //判斷是否被中斷
public static boolean Thread.interrupted() //判斷是否被中斷滴某,并清除當前中斷狀態(tài)

這兩個方法使得當前線程能夠感知到是否被中斷了(通過檢查標志位)。
所以如果希望線程 t 在中斷后停止滋迈,就必須先判斷是否被中斷霎奢,并為它增加相應的中斷處理代碼:

@Override
public void run() {
    super.run();
    for(int i = 0; i <= 200000; i++) {
        //判斷是否被中斷
        if(Thread.currentThread().isInterrupted()){
            //處理中斷邏輯
            break;
        }
        System.out.println("i=" + i);
    }
}

輸出結(jié)果,for 循環(huán)在執(zhí)行完成前就提前結(jié)束了:


image.png

在上面這段代碼中饼灿,我們增加了 Thread.isInterrupted() 來判斷當前線程是否被中斷了幕侠,如果是,則退出 for 循環(huán)碍彭,結(jié)束線程晤硕。
這種方式看起來與之前介紹的“使用標志位終止線程”非常類似悼潭,但是在遇到 sleep() 或者 wait() 這樣的操作,我們只能通過中斷來處理了舞箍。

public static native void sleep(long millis) throws InterruptedException

Thread.sleep() 方法會拋出一個 InterruptedException 異常舰褪,當線程被 sleep() 休眠時,如果被中斷疏橄,這會就拋出這個異常占拍。
(注意:Thread.sleep() 方法由于中斷而拋出的異常,是會清除中斷標記的捎迫。)

五晃酒、 線程的生命周期

線程的生命周期包含5個階段,包括:新建窄绒、就緒掖疮、運行、阻塞颗祝、銷毀浊闪。

  • 新建:就是剛使用new方法,new出來的線程螺戳;
  • 就緒:就是調(diào)用的線程的start()方法后搁宾,這時候線程處于等待CPU分配資源階段,誰先搶的CPU資源倔幼,誰開始執(zhí)行;
  • 運行:當就緒的線程被調(diào)度并獲得CPU資源時盖腿,便進入運行狀態(tài),run方法定義了線程的操作和功能;
  • 阻塞:在運行狀態(tài)的時候损同,可能因為某些原因?qū)е逻\行狀態(tài)的線程變成了阻塞狀態(tài)翩腐,比如sleep()、wait()之后線程就處于了阻塞狀態(tài)膏燃,這個時候需要其他機制將處于阻塞狀態(tài)的線程喚醒茂卦,比如調(diào)用notify或者notifyAll()方法。喚醒的線程不會立刻執(zhí)行run方法组哩,它們要再次等待CPU分配資源進入運行狀態(tài);
  • 銷毀:如果線程正常執(zhí)行完畢后或線程被提前強制性的終止或出現(xiàn)異常導致結(jié)束,那么線程就要被銷毀伶贰,釋放資源;
    完整的生命周期圖如下:
    image.png

六、 notify黍衙、join、yield的方法說明

  • notify: 在執(zhí)行notify方法后琅翻,當前線程不會馬上釋放該對象鎖位仁,呈wait狀態(tài)的線程也并不能馬上獲取該對象鎖浅妆,要等到執(zhí)行notify方法的線程將程序執(zhí)行完障癌,也就是退出synchronized代碼塊后,當前線程才會釋放鎖涛浙,而呈wait狀態(tài)所在的線程才可以獲取該對象鎖。
  • join: 在B線程里面寫threadA.join( )摄欲,B掛起轿亮,讓A運行,看起來B很禮貌讓A運行了胸墙,但其實B很虛偽,讓別人運行又不釋放鎖迟隅。
class Demo implements Runnable
{
    public void run()
    {
        for(int x=0;x<50;x++)
        {
            System.out.println(Thread.currentThread().getName()+"...."+x);
        }
    }
}

//將執(zhí)行join()方法的線程終止,釋放其CPU執(zhí)行權(quán)和執(zhí)行資格奔缠,等待join()方法所屬的線程執(zhí)行完成后,才能重新獲取CPU執(zhí)行資格
class JoinDemo
{
    public static void main(String[] args)throws Exception
    {
        Demo st=new Demo();
        
        Thread t1=new Thread(st);
        Thread t2=new Thread(st);
        t1.start();
        t1.join(); //main 線程終止校哎,等待t1線程執(zhí)行完成才繼續(xù)執(zhí)行。
        t2.start();
        //t1.join();//main 線程終止闷哆,t1和t2搶奪CPU執(zhí)行權(quán),main線程等待t1線程執(zhí)行完成才繼續(xù)執(zhí)行抱怔。
        for(int x=0;x<50;x++)
        {
            System.out.println(Thread.currentThread().getName()+"...."+x);
        }
        System.out.println("over");
    }
}
  • yield: 方法:使當前線程從執(zhí)行狀態(tài)(運行狀態(tài))變?yōu)榭蓤?zhí)行態(tài)(就緒狀態(tài))。cpu會從眾多的可執(zhí)行態(tài)里隨機選擇野蝇,也就是說括儒,當前也就是剛剛的那個線程還是有可能會被再次執(zhí)行到的绕沈。也就是從Running變?yōu)镽eady帮寻,一直在Runnable里面乍狐。
class Demo implements Runnable
{
    public void run()
    {
        for(int i=0;x<50;x++)
        {
            System.out.println(Thread.currentThread().getName()+"...."+x);
            Thread.yield();//釋放CPU執(zhí)行權(quán)固逗,注意:釋放CPU執(zhí)行權(quán)藕帜,不代表它自己不能再次獲取CPU執(zhí)行權(quán)
        }
    }
}

七惜傲、 線程的異常處理

方法一:子線程中try... catch...
public class ChildThread implements Runnable {
    public void run() {
        doSomething1();
        try {
            // 可能發(fā)生異常的方法
            exceptionMethod();
        } catch (Exception e) {
            // 處理異常
            System.out.println(String.format("handle exception in child thread. %s", e));
        }
        doSomething2();
    }
}
方法二:為線程設(shè)置“未捕獲異常處理器”UncaughtExceptionHandler

為線程設(shè)置異常處理器。具體做法可以是以下幾種:
(1)Thread.setUncaughtExceptionHandler設(shè)置當前線程的異常處理器盗誊;
(2)Thread.setDefaultUncaughtExceptionHandler為整個程序設(shè)置默認的異常處理器;
如果當前線程有異常處理器(默認沒有)哈踱,則優(yōu)先使用該UncaughtExceptionHandler類;否則开镣,如果當前線程所屬的線程組有異常處理器刀诬,則使用線程組的
UncaughtExceptionHandler邪财;否則,使用全局默認的DefaultUncaughtExceptionHandler树埠;如果都沒有的話,子線程就會退出弥奸。
注意:子線程中發(fā)生了異常,如果沒有任何類來接手處理的話盛霎,是會直接退出的,而不會記錄任何日志愤炸。
所以期揪,如果什么都不做的話规个,是會出現(xiàn)子線程任務既沒執(zhí)行成功凤薛,也沒有任何日志提示的“詭異”現(xiàn)象的诞仓。
設(shè)置當前線程的異常處理器:

public class ChildThread implements Runnable {    
    private static ChildThreadExceptionHandler exceptionHandler;

    static {
        exceptionHandler = new ChildThreadExceptionHandler();
    }

    public void run() {
        Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
        System.out.println("do something 1");
        exceptionMethod();
        System.out.println("do something 2");
    }

    public static class ChildThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println(String.format("handle exception in child thread. %s", e));
        }
    }
}

或者,設(shè)置所有線程的默認異常處理器

public class ChildThread implements Runnable {
    private static ChildThreadExceptionHandler exceptionHandler;

    static {
        exceptionHandler = new ChildThreadExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
    }

    public void run() {
        System.out.println("do something 1");
        exceptionMethod();
        System.out.println("do something 2");
    }

    private void exceptionMethod() {
        throw new RuntimeException("ChildThread exception");
    }

    public static class ChildThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println(String.format("handle exception in child thread. %s", e));
        }
    }
}

命令行輸出:
do something 1
handle exception in child thread. java.lang.RuntimeException: ChildThread exception

方法三:通過Future的get方法捕獲異常(推薦)

使用線程池提交一個能獲取到返回信息的方法活玲,也就是ExecutorService.submit(Callable)
在submit之后可以獲得一個線程執(zhí)行結(jié)果的Future對象,而如果子線程中發(fā)生了異常舒憾,通過future.get()獲取返回值時镀钓,可以捕獲到
ExecutionException異常,從而知道子線程中發(fā)生了異常镀迂。
子線程代碼:

public class ChildThread implements Callable<String> {
    public String call() throws Exception {
        System.out.println("do something 1");
        exceptionMethod();
        System.out.println("do something 2");
        return "test result";
    }

    private void exceptionMethod() {
        throw new RuntimeException("ChildThread1 exception");
    }
}

父線程代碼:

public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        Future future = executorService.submit(new ChildThread());
        try {
            future.get();
        } catch (InterruptedException e) {
            System.out.println(String.format("handle exception in child thread. %s", e));
        } catch (ExecutionException e) {
            System.out.println(String.format("handle exception in child thread. %s", e));
        } finally {
            if (executorService != null) {
                executorService.shutdown();
            }
        }
    }
}

命令行輸出:
do something 1
handle exception in child thread. java.util.concurrent.ExecutionException: java.lang.RuntimeException: ChildThread1 exception

八、 死鎖的解決方案

java 死鎖產(chǎn)生的四個必要條件:

1探遵、互斥使用,即當資源被一個線程使用(占有)時别凤,別的線程不能使用
2领虹、不可搶占,資源請求者不能強制從資源占有者手中奪取資源塌衰,資源只能由資源占有者主動釋放。
3最疆、請求和保持杯巨,即當資源請求者在請求其他的資源的同時保持對原有資源的占有。
4努酸、循環(huán)等待,即存在一個等待隊列:P1占有P2的資源获诈,P2占有P3的資源,P3占有P1的資源笼踩。這樣就形成了一個等待環(huán)路。
當上述四個條件都成立的時候嚎于,便形成死鎖。當然于购,死鎖的情況下如果打破上述任何一個條件,便可讓死鎖消失知染。下面用java代碼來模擬一下死鎖的產(chǎn)生价涝。
當上述四個條件都成立的時候,便形成死鎖色瘩。當然,死鎖的情況下如果打破上述任何一個條件居兆,便可讓死鎖消失。下面用java代碼來模擬一下死鎖的產(chǎn)生泥栖。

解決死鎖問題的方法是:一種是用synchronized,一種是用Lock顯式鎖實現(xiàn)魏割,
而如果不恰當?shù)氖褂昧随i,且出現(xiàn)同時要鎖多個對象時钞它,會出現(xiàn)死鎖情況殊鞭。

死鎖是兩個甚至多個線程被永久阻塞時的一種運行局面遭垛,這種局面的生成伴隨著至少兩個線程和兩個或者多個資源操灿。
避免死鎖方針:
a:避免嵌套封鎖:這是死鎖最主要的原因的,如果你已經(jīng)有一個資源了就要避免封鎖另一個資源庶喜。如果你運行時只有一個對象封鎖,那是幾乎不可能出現(xiàn)一個死鎖局面的溃卡。
b:只對有請求的進行封鎖:你應當只想你要運行的資源獲取封鎖.如果我們只對它所屬領(lǐng)域中的一個感興趣蜒简,那我們應當封鎖住那個特殊的領(lǐng)域而并非完全的對象瘸羡。
c:避免無限期的等待:如果兩個線程正在等待對象結(jié)束搓茬,無限期的使用線程加入,如果你的線程必須要等待另一個線程的結(jié)束卷仑,若是等待進程的結(jié)束加入最好準備最長時間。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粘昨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子张肾,更是在濱河造成了極大的恐慌,老刑警劉巖馁启,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芍秆,死亡現(xiàn)場離奇詭異惯疙,居然都是意外死亡妖啥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門蒿偎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來克伊,“玉大人酥郭,你說我怎么就攤上這事愿吹∠Ы悖” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵坷衍,是天一觀的道長。 經(jīng)常有香客問我枫耳,道長孟抗,這世上最難降的妖魔是什么迁杨? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任凄硼,我火速辦了婚禮,結(jié)果婚禮上狐史,老公的妹妹穿的比我還像新娘。我一直安慰自己骏全,他們只是感情好,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布吟温。 她就那樣靜靜地躺著,像睡著了一般潘悼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上治唤,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天糙申,我揣著相機與錄音,去河邊找鬼柜裸。 笑死,一個胖子當著我的面吹牛疙挺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铐然,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沥阳!你這毒婦竟也來了自点?” 一聲冷哼從身側(cè)響起桐罕,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤功炮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后死宣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡毅该,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挡育。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡即寒,死狀恐怖召噩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情具滴,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布构韵,位于F島的核電站,受9級特大地震影響疲恢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棚愤,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一萎攒、第九天 我趴在偏房一處隱蔽的房頂上張望遇八。 院中可真熱鬧耍休,春花似錦货矮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抓督。三九已至,卻和暖如春阵具,著一層夾襖步出監(jiān)牢的瞬間碍遍,已是汗流浹背阳液。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留帘皿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓虽填,卻偏偏與公主長得像,于是被迫代替她去往敵國和親卤唉。 傳聞我的和親對象是個殘疾皇子仁期,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

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

  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,959評論 1 18
  • 進程:正在執(zhí)行的程序,是一個動態(tài)的過程 線程:是進程中用于控制程序執(zhí)行的控制單元(執(zhí)行路徑熬的,執(zhí)行情景) 進程中至少...
    寶塔山上的貓閱讀 441評論 0 1
  • 本文主要講了java中多線程的使用方法赊级、線程同步押框、線程數(shù)據(jù)傳遞理逊、線程狀態(tài)及相應的一些線程函數(shù)用法、概述等晋被。 首先講...
    李欣陽閱讀 2,456評論 1 15
  • 林炳文Evankaka原創(chuàng)作品。轉(zhuǎn)載自http://blog.csdn.net/evankaka 本文主要講了ja...
    ccq_inori閱讀 654評論 0 4
  • 原創(chuàng) | 義芳君說茶 要說中國最讓世界驚艷的東西實在有很多刁俭,譬如:絲綢、瓷器牍戚、書法……沙兰,當然還包括茶葉翘魄。 人們常常...
    義芳君說茶閱讀 253評論 0 0