基礎知識

用多線程只有一個目的:更好的利用cpu資源。

更詳細的說:

  • 系統需要多功能處理,開啟進程非常耗費資源
  • 進程間的通訊很不方便,因為大多數操作系統不允許進程訪問其他進程的內存空間
  • 因為多線程程序是亂序執行,每次執行的結果都是隨機的。因此,只有亂序執行的代碼才有必要設計為多線程。

關於線程的一些概念:

  • cpu時間片:我們操作系統看起來可以多個程序同時運行,分時操作系統,將系統劃分成相同的時間區域,並分配給一個線程使用。 當線程還沒有結束,時間片已經過去,該線程只有先停止,等待下一個時間片。cpu運行很快,中間的停頓感覺不出來。
  • 多線程:指的是這個程序(一個進程)運行時產生了不止一個線程(比如:下載程序,開啟多個線程同時運行)。
  • 並行:多個cpu實例或者多台機器同時執行一段處理邏輯,是真正的同時。
  • 並發:通過cpu調度算法,讓用戶看上去同時執行,實際上從cpu操作層面不是真正的同時。並 發往往在場景中有公用的資源,那麼針對這個公用的資源往往產生瓶頸,我們會用TPS(Transactions Per Second)或QPS(Query Per Second)來反應這個系統的處理能力。 (See 【Teradata】系统吞吐量重要参数QPS(TPS)、并发数、响应时间 - 李子恒 - 博客园
  • 線程安全:經常用來描繪一段代碼。指在並發的情況下,該代碼經過多線程使用,線程的調度順序不影響任何結果。這個時候使用多線程, 我們只需要關注系統的內存,cpu是不是夠用即可。反過來,線程不安全意味著線程的調度順序會影響最終結果。
  • 同步:通過人為的控制和調度,保證共享資源的多線程訪問成為線程安全,來保證結果的準確。

線程安全的優先級 > 性能。

Ref: Java多线程的实现 - - SegmentFault 思否

並發與並行

並發,指的是多個事情,在同一時間段內同時發生。
並行,指的是多個事情,在同一時間點上同時發生。

並發的多個任務之間是互相搶佔資源。
並行的多個任務之間是不互相搶佔資源。

只有在多cpu的情況中,才會發生並行。否則,看似同時發生的事情,其實都是並發執行的。

Ref: 面试必考的:并发和并行有什么区别?

進程與線程

進程:

進程是程序的一次執行過程,是系統運行程序的基本單位,因此進程是動態的。系統運行一個程序即是一個進程從創建、運行到消亡的 過程。簡單來說,一個進程就是一個執行中的程序,它在計算機中一個指令接著一個指令的運行著,同時,每個進程還佔有某些系統資 源如cpu時間、內存空間、文件設備的使用權等等。換句話說,當程序在執行時,將會被操作系統載入內存。

線程:

線程與進程相似,但線程是一個比進程更小的執行單位,一個進程在其執行的過程中可以產生多個線程。與進程不同的是同類的多個線 程共享同一塊內存空間和一組系統資源,所以系統在產生一個線程,或是在各個線程之間作切換工作時,負擔要比進程小得多。

用比喻的方式說明:

1。单进程单线程:一个人在一个桌子上吃菜。
2。单进程多线程:多个人在同一个桌子上一起吃菜。
3。多进程单线程:多个人每个人在自己的桌子上吃菜。

多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸 出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个 人夹菜,也就是说资源共享就会发生冲突争抢。

Ref: 多线程有什么用? - 知乎

同步與異步

消息通信機制:

  • 同步(synchronous communication):需要等待request回調
  • 異步(asynchronous communication):不需等待request回調

Ref: 怎样理解阻塞非阻塞与同步异步的区别? - 知乎

Java與多線程關係

單線程方法調用鏈(main)

class Demo1 {
    public static void main(String[] args) {
        m1();
    }

    public static void m1() {
        m2();
        m3();
    }

    public static void m2() {
    }

    public static void m3() {
    }
}


開啟多線程

class Demo2 implements Runnable {
    public static void main(String[] args) {
        Demo2 demo2 = new Demo2();
        Thread thread = new Thread(demo2);
        thread.start();
    }

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

參考

架構:

思維導圖:

並發依賴:

基礎:

面試題目: