線程與常見線程池與核心參數

進程與線程

兩者的區別:

  1. 進程是計算機資源(CPU、內存等)分配基本單位;爲避免進程間的互相干擾,每個進程都擁有自己獨立的地址空間。

  2. 線程是CPU調度和分派的基本單位,是程序執行時的最小單位;一個進程可以由很多個線程組成;線程間共享進程的所有資源,每個線程有自己的堆棧和局部變量。

  3. 線程切換的速度,高於進程切換的速度;線程創建的開銷,低於進程創建的開銷

  4. 多進程的程序更加健壯。多線程程序中,一個 線程的崩潰 ,很有可能導致整個進程結束,但一個 進程的崩潰 ,並不會影響其他進程。

  5. 線程間的通信可以使用進程中共享的數據來實現,進程間的通信有如下幾種方式

進程間的通信方式:

  1. 管道(半雙工下的父子進程的通信)》》流管道(全雙工的父子進程通信)》》命名管道(全雙公共的任意進程的通信)

  2. 信號量:主要應用於進程或同一進程內不同線程的同步

  3. 消息隊列:適合需要承載多信息量的通信

  4. 共享內存:開闢一塊各個進程都可以訪問的內存區域,通常與信號量結合起來實現同步互斥

  5. 套接字(Socket)/ 遠程過程調用(RPC) :應用於不同機器,不同進程間的通信

更多關於進程通信的介紹

線程間的通信方式:

  1. 鎖機制:包括互斥鎖、條件變量、讀寫鎖
    互斥鎖:提供了以排他方式防止數據結構被併發修改的方法。
    讀寫鎖:允許多個線程同時共享數據,而對寫操作是互斥的。
    條件變量:可以以原子的方式阻塞進程,直到某個特定條件爲真爲止。對條件的測試是在互斥鎖的保護下進行的。條件變量始終與互斥鎖一起使用。

  2. 信號量機制(Semaphore):包括無名進程信號量和命名線程信號量

  3. 信號機制(Signal):類似進程間的信號處理

Java中線程的通信方式:

  1. 使用關鍵字 synchronized 同步

  2. 使用 Object 下的 wait 和 notify 來阻塞和喚醒線程

  3. Lock類下的 lock 和 trylock 同步

fork函數對進程的複製,執行:

  1. fork函數在複製子線程的過程中,會有關於標準IO庫是帶緩衝的,緩存區未被刷新,將被子線程複製;緩存區被刷新,子線程不會複製到其中內容(標準輸出(printf之類的)的緩衝區由換行符刷新,但換行符不會刷新文件的緩衝區)

  2. fork函數雖然複製了整個進程,但其是從fork的位置下,開始執行子進程的

  3. fork函數將返回一個pid,這個pid在父進程中是子進程的pid值,在子進程中pid爲0

記住上面三條後,然後參考兩個用例對其的解釋:

https://it.baiked.com/dev/1027.html :::::: https://www.cnblogs.com/tp-16b/p/9005079.html

更多Linux進程介紹


線程生命週期的五種狀態(出生、就緒、執行、阻塞、死亡):

在這裏插入圖片描述

創建線程的三種方式:

繼承Thread / 實現Runnable接口 / FutureTask和Callable創建有返回值的子線程

三種方式下的多線程使用的安全用例


四種類型的線程池

Executors.newFixedThreadPool(int nThreads):

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

創建nThreads個不被回收的線程

線程無超時機制銷燬

任務隊列不限長

newCachedThreadPool:

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

只要有任務來到,且當前無空閒線程,就在線程池中創建新線程

60s超時機制銷燬空閒線程

newSingleThreadExecutor:

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

只創建一個線程

任務隊列不限長

ScheduledThreadPool

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

用來處理延時任務或定時任務

核心對象ThreeadPoolExecutor構造器:

//五個參數的構造函數
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue)
 
//六個參數的構造函數-1
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory)
 
//六個參數的構造函數-2
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler)
 
//七個參數的構造函數
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

參數含義:

int corePoolSize:該線程池中核心線程數最大值核心線程

線程池新建線程的時候,如果當前線程總數小於corePoolSize,則新建的是核心線程,如果超過corePoolSize,則新建的是非核心線程,核心線程默認情況下會一直存活在線程池中,即使爲閒置狀態。如果指定ThreadPoolExecutor的allowCoreThreadTimeOut這個屬性爲true,那麼核心線程如果不幹活(閒置狀態)的話,超過一定時間(時長下面參數決定),就會被銷燬掉。

int maximumPoolSize: 該線程池中線程總數最大值
線程總數 = 核心線程數 + 非核心線程數。

long keepAliveTime:該線程池中非核心線程閒置超時時長

一個非核心線程,如果不幹活(閒置狀態)的時長超過這個參數所設定的時長,就會被銷燬掉,如果設置allowCoreThreadTimeOut = true,則會作用於核心線程。

TimeUnit unit:keepAliveTime時間單位

BlockingQueue workQueue:該線程池中的任務隊列,維護着等待執行的Runnable對象

當所有的核心線程都在幹活時,新添加的任務會被添加到這個隊列中等待處理,如果隊列滿了,則新建非核心線程執行任務。

常用的workQueue類型:

  • SynchronousQueue:這個隊列接收到任務的時候,會直接提交給線程處理,而不保留它,如果所有線程都在工作怎麼辦?那就新建一個線程來處理這個任務!所以爲了保證不出現<線程數達到了maximumPoolSize而不能新建線程>的錯誤,使用這個類型隊列的時候,maximumPoolSize一般指定成Integer.MAX_VALUE,即無限大

  • LinkedBlockingQueue:這個隊列接收到任務的時候,如果當前線程數小於核心線程數,則新建線程(核心線程)處理任務;如果當前線程數等於核心線程數,則進入隊列等待。由於這個隊列沒有最大值限制,即所有超過核心線程數的任務都將被添加到隊列中,這也就導致了maximumPoolSize的設定失效,因爲總線程數永遠不會超過corePoolSize

  • ArrayBlockingQueue:可以限定隊列的長度,接收到任務的時候,如果沒有達到corePoolSize的值,則新建線程(核心線程)執行任務,如果達到了,則入隊等候,如果隊列已滿,則新建線程(非核心線程)執行任務,又如果總線程數到了maximumPoolSize,並且隊列也滿了,則發生錯誤

  • DelayQueue:隊列內元素必須實現Delayed接口,這就意味着你傳進去的任務必須先實現Delayed接口。這個隊列接收到任務時,首先先入隊,只有達到了指定的延時時間,纔會執行任務

ThreadFactory threadFactory:創建線程的方式,這是一個接口,你new他的時候需要實現他的Thread newThread(Runnable r)方法
RejectedExecutionHandler handler: 當提交任務數超過maxmumPoolSize+workQueue之和時,任務會交給RejectedExecutionHandler來處理;

jdk1.5提供了四種飽和策略 :

  • AbortPolicy :默認。直接拋異常(RejectedExecutionException)。

  • CallerRunsPolicy :只用調用者所在的線程執行任務,重試添加當前的任務,它會自動重複調用execute()方法

  • DiscardOldestPolicy :丟棄任務隊列中最久的任務。

  • DiscardPolicy :丟棄當前任務。

更多詳解可參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章