一文搞懂Java多線程基礎內(nèi)容

一魁巩、首先什么是線程和進程?

進程好比我們電腦里開的程序姐浮,比如dota谷遂、英雄聯(lián)盟、網(wǎng)易云音樂卖鲤,每個程序都是一個獨立的進程肾扰;然后每個程序中畴嘶,會有多個線程,比如英雄聯(lián)盟游戲里有畫面集晚、有音樂窗悯,這就是不同的線程。

二、java中實現(xiàn)多線程的三種方法

1、繼承Thread類买决,重寫run方法
2、實現(xiàn)Runnable接口欺旧,重寫run方法
3、實現(xiàn)Callbale接口蛤签,重寫call方法

手撕代碼:

package com.xusujun.thread_finish;
import static java.util.concurrent.Executors.newFixedThreadPool;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        DemoClass demoClass = new DemoClass();
        demoClass.setName("通過繼承thread類實現(xiàn)");
        demoClass.start();// 繼承實現(xiàn)的可以直接調用start方法啟動線程

        DemoRunnable demoRunnable = new DemoRunnable();
        // 通過runnable接口實現(xiàn)的辞友,需要通過thread類進行代理實現(xiàn)
        new Thread(demoRunnable, "通過runnable接口實現(xiàn)").start();

        DemoCallable demoCallable = new DemoCallable();
        // 創(chuàng)建服務
        ExecutorService ser = newFixedThreadPool(1);
        // 提交服務
        Future<Boolean> r = ser.submit(demoCallable);
        // 獲取結果
        boolean result = r.get();
        // 關閉服務
        ser.shutdown();

    }
}

// 通過繼承thread類實現(xiàn),重寫run方法
class DemoClass extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "執(zhí)行了");
    }
}

// 通過實現(xiàn)Runnable接口實現(xiàn)震肮,重寫run方法
class DemoRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "執(zhí)行了");
    }

}

// 通過callable接口實現(xiàn),重寫call方法
class DemoCallable implements Callable<Boolean> {

    @Override
    public Boolean call() throws Exception {
        Thread.currentThread().setName("通過callbale接口實現(xiàn)");
        System.out.println(Thread.currentThread().getName() + "執(zhí)行了");
        return true;
    }

}

以上代碼執(zhí)行結果如下:


image.png

三種方法個人粗略總結:
1称龙、通過繼承Thread類實現(xiàn),對象可以直接調用Thread類靜態(tài)方法戳晌,入start茵瀑、sleep等。由于單繼承的原因躬厌,靈活性不夠,Thread類其本質也是實現(xiàn)runnable接口竞帽。
2扛施、通過實現(xiàn)runnable接口方法更靈活,但是需要Thread類來進行代理實現(xiàn)
3屹篓、callable重寫的call方法有返回值疙渣,run方法沒有返回值。call可以拋出異常堆巧,run方法無法拋出異常

三妄荔、線程的生命周期

通過上面的例子,大概能感覺出來線程的生命周期包括:

  1. 創(chuàng)建 對象實例化
  2. 就緒 .start() 啟動不代表立即執(zhí)行谍肤,由cpu自行調度
  3. 運行 .run() 獲取系統(tǒng)資源開始運行
  4. 等待 .sleep() 休眠狀態(tài) .wait() 等待狀態(tài)
  5. 結束 運行結束啦租,線程一旦運行結束無法重新啟動。推薦使用外部標志位進行停止荒揣,不推薦使用stop等方法篷角。

關于sleep,一條重點系任,執(zhí)行sleep不會導致解鎖

四恳蹲、龜兔賽跑案例

假設龜兔分別代表兩個線程虐块,我們讓他們進行50米比賽,假設我們不人工干預讓他們兩個線程自己跑嘉蕾,你們想下會有什么結果贺奠?
看代碼:

//龜兔賽跑
public class ThreadDemo {

    static class Mythread implements Runnable {
        int raceway = 50; //賽道設置50米
        Boolean flag = false; //比賽是否結束標志
        String winner; //獲勝者

        @Override
        public void run() {
            while (raceway >= 0) {
                if (flag == true) {
                    break;
                }
                raceway--;
                System.out.println(Thread.currentThread().getName() + "距離終點" + raceway + "米 !");
                gameOver(raceway);

            }
        }

        //是否獲勝方法
        public void gameOver(int distance) {
            if (winner != null) {
                this.flag = true;
            }
            if (distance == 0) {
                this.flag = true;
                winner = Thread.currentThread().getName();
                System.out.println(winner + "獲得了勝利");
            }

        }
    }

    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        new Thread(mythread, "兔子").start(); //兔子線程
        new Thread(mythread, "烏龜").start(); //烏龜線程
    }
}

如果我們按照上面的程序跑,結果是不是可能烏龜獲勝错忱,也可能兔子獲勝啊儡率,因為之前說過線程的啟動是cpu自行調度的。那么龜兔賽跑的故事是不是有兔子睡覺啊航背,那么我們加入兔子睡覺再來看喉悴,在run()方法中加入如下代碼:

if (Thread.currentThread().getName().equals("兔子")) {
    try {
        Thread.sleep(200);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

以上代碼先找到兔子的線程,然后通過sleep()方法讓他睡覺200毫秒玖媚,這樣一來是不是每次都是烏龜獲勝了呀箕肃!

image.png
image.png

五、sleep今魔、yield勺像、join 一起

sleep ---線程休眠
yield ---線程禮讓
join ---線程插隊

直接上例子更好理解

1、sleep例子:
class ThreadDemoread {

    static class Mythread implements Runnable {

        @Override
        public void run() {

            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("當前時間:" + printDate());
            }
        }

        // 每隔一秒打印當前時間方法
        public String printDate() {
            // 獲取系統(tǒng)當前時間
            Date now = new Date(System.currentTimeMillis());
            String formatDate = new SimpleDateFormat("HH:mm:ss").format(now);
            return formatDate;
        }

    }

    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        new Thread(mythread).start();
    }
}

執(zhí)行結果如下:


image.png
2错森、yeild例子:
public class ThreadDemo {

    static class Mythread implements Runnable {

        @Override
        public void run() {
            if (Thread.currentThread().getName().equals("A")) {
                 Thread.yield();
             }
            System.out.println(Thread.currentThread().getName() + "執(zhí)行了");
            System.out.println(Thread.currentThread().getName() + "結束了");
        }
    }

    public static void main(String[] args) {
        new Thread(new Mythread(), "A").start();
        new Thread(new Mythread(), "B").start();
    }
}

在run方法中添加yield后吟宦,線程A會進行線程禮讓,但是注意涩维,禮讓不一定成功殃姓,依舊是看cpu心情。也就是說可能禮讓成功瓦阐,也可能禮讓失敗蜗侈。

3、join

join是強制執(zhí)行睡蟋,他就比較霸道了踏幻,類似于vip,vip來了戳杀,其他人都要讓位子

public class ThreadDemo {

    static class Mythread implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 200; i++) {
                System.out.println(Thread.currentThread().getName() + "執(zhí)行了" + i + "次");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Mythread mythread = new Mythread();
        Thread thB = new Thread(mythread, "VIP");
        thB.start();
        for (int i = 0; i < 600; i++) {
            if(i==10){
                thB.join();//main線程阻塞
            }
            System.out.println("main線程執(zhí)行了" + i + "次");
        }
    }
}

以上代碼當main線程打印到第10次的時候该面,vip線程就會插入強制優(yōu)先執(zhí)行,main線程會被阻塞信卡,等待vip執(zhí)行完才能繼續(xù)執(zhí)行隔缀。結果如下:


image.png

六、線程狀態(tài)和優(yōu)先級

1傍菇、線程狀態(tài)

既然線程有生命周期蚕泽,那就可以觀測線程的狀態(tài) Thread.State

1、new
2、runnable
3须妻、blocked
4仔蝌、waiting
5、timed_waiting
6荒吏、terminated
上代碼:

class ThreadDemo {
    static class Mythread implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("******");
        }

    }

    public static void main(String[] args) throws InterruptedException {
        Mythread mythread = new Mythread();
        Thread thread = new Thread(mythread, "線程A");
        Thread.State state = thread.getState();
        //觀察狀態(tài)
        System.out.println(state);// new

        thread.start();
        state = thread.getState();
        System.out.println(state); // runnable

        while (state != Thread.State.TERMINATED) {
            Thread.sleep(100);
            state = thread.getState();
            System.out.println(state);
        }

    }
}

運行結果如下:

image.png

2敛惊、線程優(yōu)先級
每個線程都有一個優(yōu)先級,從1到10上升绰更,數(shù)字越大優(yōu)先級越高瞧挤,如果我們在創(chuàng)建一個線程的手不設置優(yōu)先級,那么默認的優(yōu)先級是5儡湾。
設置優(yōu)先級使用thread.setPriority(value)方法進行設置特恬。通過thread.getPriority()可以獲得線程優(yōu)先級數(shù)值。

七徐钠、Lamada表達式

lamada表達式是函數(shù)式編程的思想癌刽,看過js的我看到這個第一反應就是臥槽 這不就是es6里的箭頭函數(shù)嗎?尝丐?
先看這么一句話:

任何一個接口如果只包含一個抽象方法显拜,那么這個接口就可以稱作函數(shù)式接口,對于函數(shù)式接口爹袁,我們就可以使用lamada表達式來創(chuàng)建對象远荠。
如:
new Thread(()->System.out.println(”lamada表達式創(chuàng)建的線程"));

現(xiàn)在可能有的朋友看起來會比較懵逼,下面我們手撕代碼失息,順便復習下javase中的各種不同名稱的類譬淳,大家腦子里趕緊想下有哪些類的寫法?
我們先把頭寫好盹兢,主函數(shù)以及自定義一個函數(shù)是接口瘦赫,也就是只有一個抽象方法的接口say。

public class ThreadDemo{
    public static void main(String[] args) {
        
    }
}

//定義一個函數(shù)式接口
interface Say{
    void say(); //只有一個說話的方法
}

1蛤迎、常規(guī)寫法:

//接口的實現(xiàn)類
class Person implements Say{

    @Override
    public void say() {
        System.out.println("我在學lamada表達式-常規(guī)寫法");
    }
}

補全主函數(shù)內(nèi)容:
public class ThreadDemo{
    public static void main(String[] args) {
        Person person = new Person();
        person.say();
    }
}

運行后應該會打印我在學lamada表達式-常規(guī)寫法
2、實現(xiàn)類寫在外面是不是不好看啊含友,我們可以把它放到主類里面替裆,就構成靜態(tài)內(nèi)部類,改造:

public class ThreadDemo {

    // 接口的實現(xiàn)類-靜態(tài)內(nèi)部類
    static class Person implements Say {

        @Override
        public void say() {
            System.out.println("我在學lamada表達式-靜態(tài)內(nèi)部類");
        }
    }

    public static void main(String[] args) {
        Person person = new Person();
        person.say();
    }
}

3窘问、這時候有的同學可能要說了我能不能把實現(xiàn)類寫到主函數(shù)方法里辆童?這就是局部內(nèi)部類

public class ThreadDemo {

    public static void main(String[] args) {
        // 接口的實現(xiàn)類-局部內(nèi)部類
        class Person implements Say {
            @Override
            public void say() {
                System.out.println("我在學lamada表達式-局部內(nèi)部類");
            }
        }
        Person person = new Person();
        person.say();
    }
}

4、匿名內(nèi)部類
以上這些寫法是不是實現(xiàn)類都有名字啊惠赫,也就是Person把鉴,我們能不能不要名字,再作簡化?直接通過接口來創(chuàng)建對象

public class ThreadDemo {

    public static void main(String[] args) {

        Say person = new Say() {

            @Override
            public void say() {
                System.out.println("我在學lamada表達式-匿名內(nèi)部類");
            }
        };
        person.say();
    }
}

5庭砍、還想要簡化场晶?那就要請出lamada表達式了
之前說過,只有一個抽象方法的接口可以采用lamada表達式怠缸,我們這個say接口是不是只有一個say方法啊诗轻,如何寫?趕緊自己想下

public class ThreadDemo {

    public static void main(String[] args) {

        Say person = ()->System.out.println("我在學lamada表達式-lamada寫法");
        person.say();
    }
}

和上面那些寫法相比是不是減少了大量代碼揭北,更簡潔了呀扳炬。那么有的同學要問了,我只能寫一句代碼嗎搔体?我想寫多條內(nèi)容可以嗎恨樟?當然可以,加上大括號就可以了:

Say person = () -> {
            System.out.println("我在學lamada表達式-lamada寫法");
            System.out.println("多輸出一句話也OK拉");
        };
        person.say();

而且lamada表達式也支持參數(shù)疚俱,具體寫法這里就不多說了劝术,感興趣的自己去了解吧!

八计螺、暴露問題-重要

前面學了很多相關的基礎內(nèi)容夯尽,感覺寫的還挺順利,多線程也挺厲害登馒,可以同時執(zhí)行多個任務匙握,那么多線程會出問題嗎?我們先來看一個例子陈轿,搶購火車票:

class ThreadDemo {

    static class BuyTicket implements Runnable {

        private int tickets = 10; // 總共有10張票
        boolean flag = true; // 搶購是否結束標志

        @Override
        public void run() {
            while (flag) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                buy();

            }

        }

        // 購票
        synchronized void buy() {
            if (tickets == 0) {
                this.flag = false;
            } else {
                System.out.println(Thread.currentThread().getName() + "搶到了第" + tickets-- + "票圈纺!");
                if (tickets == 0) {
                    this.flag = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        BuyTicket buy = new BuyTicket();
        new Thread(buy, "小明").start();
        new Thread(buy, "小紅").start();
        new Thread(buy, "可惡的黃牛").start();
    }
}

大家看下上面代碼,先想想以上代碼會輸出什么麦射,會有問題嗎蛾娶?

直接運行看下結果:
image.png

是不是發(fā)現(xiàn)很多問題啊,搶到同一張票潜秋,出現(xiàn)負數(shù)的票等蛔琅,為什么會出現(xiàn)這個問題?因為多線程他們是同時進入開始操作是吧峻呛,這個問題出現(xiàn)于當多個對象使用同一份資源的時候罗售,因為多線程對資源的操作是如何操作的?是把資源拷貝到自己的內(nèi)存空間然后進行操作吧钩述,也就是說小紅寨躁、小明、黃牛這3個線程可能會同時分別把同一個資源拷貝到自己的內(nèi)存空間進行操作牙勘,也就出現(xiàn)同時搶到了职恳,但是實際服務器里并沒有,當他們都搶完后,服務器會顯示負數(shù)張票對吧放钦。

如何解決這個問題呢色徘?就要引入線程同步機制了,通過同步方法和同步塊來解決最筒,關鍵詞:synchronized 本質就是加鎖讓他們排隊贺氓。

舉個栗子:大家去熱門景點游玩,都肚子疼床蜘,但是廁所只有一個辙培,大家想象一下,大家同時進去會出現(xiàn)怎樣的場景邢锯,是不是會打架啊扬蕊,排隊是不是就能解決了?一個個去嘛

我們上代碼看如何解決上面這個問題丹擎?

1尾抑、同步方法:

// 購票
        synchronized void buy() {
            if (tickets == 0) {
                this.flag = false;
            } else {
                System.out.println(Thread.currentThread().getName() + "搶到了第" + tickets-- + "票!");
                if (tickets == 0) {
                    this.flag = false;
                }
            }
        }

在run方法前加上synchronized蒂培,就可以了再愈,再次運行,結果如下:


image.png

加入同步機制护戳,讓他們進行排隊購票翎冲,就不會再出現(xiàn)上面那種問題了吧。

2媳荒、同步塊

我們再來看另一個例子抗悍,你有一張銀行卡,卡里有10萬钳枕,今天同一時間你和你媳婦同時用錢缴渊,你用網(wǎng)銀消費8W,你老婆呢刷卡消費8W鱼炒,代碼如下:

class ThreadDemo {
    public static void main(String[] args) {
        Back back = new Back(new Account("8888", 10), 8);
        new Thread(back, "你自己").start();
        new Thread(back, "你媳婦").start();
    }
}

// 賬戶
class Account {
    String id; // 卡號
    int money; // 卡里的錢

    public Account(String id, int money) {
        this.id = id;
        this.money = money;
    }
}
//銀行
class Back implements Runnable {

    Account account;
    int takeMoney; // 取多少錢

    public Back(Account account, int takeMoney) {
        this.account = account;
        this.takeMoney = takeMoney;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
            takeoutMoney();
    }

    // 取錢
    void takeoutMoney() {
        System.out.println(Thread.currentThread().getName() + " 你好衔沼,當前賬戶剩余:" + account.money + "萬");
        if (account.money < takeMoney) {
            System.out.println(Thread.currentThread().getName() + ": 當前賬戶余額不足");
        } else {
            int leftMoney = account.money - takeMoney;
            System.out.println(Thread.currentThread().getName() + "消費成功!當前余額:" + leftMoney);
            account.money = leftMoney;
        }
    }
}

大家看下代碼后先想想會輸出什么內(nèi)容昔瞧?
是不是你自己和媳婦能分別消費8萬啊


image.png

這種情況是我們想看到的嗎指蚁?當然是了呀。但是我估計很快銀行就都倒閉了硬爆。
雖然你跟你媳婦是同時操作,但是是不是應該讓他們排隊啊擎鸠,肯定有個先后順序缀磕,我們看用同步塊來解決這個問題:

//添加同步塊,將賬號信息鎖定
        synchronized(account){
            takeoutMoney(); 
        }

以上什么意思呢,同步塊可以鎖定一個對象袜蚕,讓多個對象操作這個對象的時候進行排隊糟把,也就是我用的時候給他鎖住,其他人用不了牲剃,我用完了解鎖遣疯,我媳婦才能再用。
現(xiàn)在你和媳婦再去操作結果就會這樣了:


image.png

記住同步方法的默認鎖定對象是this凿傅,而同步塊是具體你指定的對象

3缠犀、Lock鎖

前面說的同步方法和同步塊都是隱式的進行加鎖和解鎖吧,我們是看不到鎖的聪舒,但是lock鎖是可以自己定義和自己釋放的辨液,想鎖哪里就鎖哪里,我們看代碼
還是那個買火車票的例子:

class ThreadDemo {
    static class BuyTicket implements Runnable {
        int num = 10;

        @Override
        public void run() {
            while (num > 0) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "買到了第" + num-- + "張票");
            }
        }

    }

    public static void main(String[] args) {
        BuyTicket buy = new BuyTicket();
        new Thread(buy, "小紅").start();
        new Thread(buy, "張三").start();
        new Thread(buy, "黃牛").start();
    }
}

輸出結果現(xiàn)在大家應該都清晰了吧箱残,會有問題是吧滔迈,現(xiàn)在我們通過顯示的添加lock鎖來解決同步問題,修改部分代碼:

        // 創(chuàng)建一把鎖
        private final ReentrantLock lock = new ReentrantLock();

        @Override
        public void run() {
            try {
                lock.lock(); // 在需要鎖定的區(qū)域添加鎖
                while (num > 0) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "買到了第" + num-- + "張票");
                }
            } finally {
                lock.unlock(); // 釋放鎖
            }
        }

記住這么一句話:鎖lock.lock 必須緊跟在try代碼塊被辑,且unlock必須寫在finally代碼塊的第一行燎悍。

關于死鎖

知道了同步方法和同步塊后,我們來想這么一個問題盼理,比如有兩個小孩分別有汽車和飛機谈山,同時呢他們又想去拿對方的玩具,自己的玩具又不肯松手榜揖,這會導致什么問題勾哩?是不是兩邊就僵持住了呀,在多線程中举哟,互相抱著對方的資源思劳,又不肯釋放自己資源的現(xiàn)象叫死鎖,我們應該避免死鎖的出現(xiàn)妨猩。具體這里就不展開了潜叛,同學們可以自行查閱相關資料了解學習。

九壶硅、生產(chǎn)者-消費者問題-重點

什么是生產(chǎn)者-消費者模式威兜?還是舉個栗子:你去肯德基買吃的,你跟前臺小姐姐說你要一個漢堡庐椒,她是不是會看櫥窗里還有沒有貨啊椒舵,有的話她就會賣給你,沒有她是不是會喊后面的阿姨做啊约谈,然后會喊你等一會是吧笔宿。如果櫥窗的容量只有10個漢堡犁钟,而里面已經(jīng)有10個了,她是不是會喊阿姨先別做了呀泼橘,這個就是一個簡單的生產(chǎn)者-消費者模式涝动,你和阿姨之間存在一個小姐姐作為你們的緩沖。這樣做有什么好處熬婷稹醋粟?你和阿姨是不是都是獨立的呀,由前臺小姐姐負責你們之間的業(yè)務呀重归,而且不會出現(xiàn)漢堡放不下了阿姨還在一直做米愿,或者櫥窗已經(jīng)沒東西了,還在不斷讓消費者購買提前。

廢話不多說吗货,擼個代碼:

public class ThreadDemo {
    public static void main(String[] args) {
        Container container = new Container();
        new Thread(new Product(container)).start();
        new Thread(new Cunsumer(container)).start();
    }
}

// 緩沖區(qū)容器類
class Container {

    int goods = 0;

    //生產(chǎn)商品方法
    synchronized void put() {
        while (goods >= 5) {
            System.out.println("產(chǎn)品已滿");
            try {
                this.wait(); //通知生產(chǎn)者等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("生產(chǎn)了第" + goods++ + "個產(chǎn)品");
        notifyAll(); //通知消費者消費
    };

    //消費東西方法
    synchronized void pop() {
        while (goods <= 0) {
            System.out.println("已經(jīng)沒有產(chǎn)品了");
            try {
                this.wait(); //通知消費者等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("消費了第" + goods-- + "個產(chǎn)品");
        notify(); //通知生產(chǎn)者生產(chǎn)

    }

}

// 生產(chǎn)者
class Product implements Runnable {
    Container container;

    public Product(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            container.put();
        }
    }

}

// 消費者
class Cunsumer implements Runnable {
    Container container;

    public Cunsumer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            container.pop();
        }
    }

}

我們運行后看下結果:


image.png

現(xiàn)在可以看到生產(chǎn)多少才會消費多少,不會過度生產(chǎn)也不會過度消費狈网。

十宙搬、總結

多線程中還有守護線程、線程池等其他內(nèi)容和概念拓哺,這里就不多展開說了勇垛,有興趣的同學可以自行查閱相關資料。而且關于上面講的內(nèi)容我這里都只是粗淺的個人見解和認識士鸥,尤其是多線程的進階還有juc等高階內(nèi)容闲孤,我還沒學到所以這篇文章更多的是對多線程基礎知識的梳理,正所謂溫故而知新烤礁,希望這篇文章可以幫助到你讼积。

感謝您的閱讀,有出錯的地方還望見諒和指出脚仔。
我們下一篇文章見勤众!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鲤脏,隨后出現(xiàn)的幾起案子们颜,更是在濱河造成了極大的恐慌,老刑警劉巖猎醇,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窥突,死亡現(xiàn)場離奇詭異,居然都是意外死亡硫嘶,警方通過查閱死者的電腦和手機阻问,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沦疾,“玉大人称近,你說我怎么就攤上這事贡蓖。” “怎么了煌茬?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長彻桃。 經(jīng)常有香客問我坛善,道長,這世上最難降的妖魔是什么邻眷? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任眠屎,我火速辦了婚禮,結果婚禮上肆饶,老公的妹妹穿的比我還像新娘改衩。我一直安慰自己,他們只是感情好驯镊,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布葫督。 她就那樣靜靜地躺著,像睡著了一般板惑。 火紅的嫁衣襯著肌膚如雪橄镜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天冯乘,我揣著相機與錄音洽胶,去河邊找鬼。 笑死裆馒,一個胖子當著我的面吹牛姊氓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播喷好,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼翔横,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绒窑?” 一聲冷哼從身側響起棕孙,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎些膨,沒想到半個月后蟀俊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡订雾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年肢预,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洼哎。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡烫映,死狀恐怖沼本,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锭沟,我是刑警寧澤抽兆,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站族淮,受9級特大地震影響辫红,放射性物質發(fā)生泄漏。R本人自食惡果不足惜祝辣,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一贴妻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蝙斜,春花似錦名惩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稚伍,卻和暖如春底循,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背槐瑞。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工熙涤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人困檩。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓祠挫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親悼沿。 傳聞我的和親對象是個殘疾皇子等舔,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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