本次整理的內容以下:java
進程是一個可執行的程序,是系統資源分配的基本單位;線程是進程內相對獨立的可執行單元,是操做系統進行任務調度的基本單位。算法
因爲每一個進程都有獨立的內存空間,進程之間的數據交換須要經過操做系統內核。須要在操做系統內核中開闢一塊緩衝區,進程 A 將須要將數據拷貝到緩衝區中,進程 B 從緩衝區中讀取數據。由於共享內存沒有互斥訪問的功能,需配合信號量進行互斥訪問。編程
管道的實現方式:小程序
管道的特色:
只容許具備血緣關係的進程間通信,只容許單向通信,進程在管道在,進程消失管道消失。管道內部經過環形隊列實現。
有名管道(命名管道):
經過文件的方式實現進程間的通訊。容許無血緣關係的進程間的通訊數組
由消息組成的鏈表,存在系統內核中。克服了信號量傳遞的信息少,管道只能承載無格式的字符流及緩衝區的大小受限等特色。經過消息類型區分消息。服務器
本質是一個計數器,不以傳送數據爲目的,主要用來保護共享資源,使得資源在一個時刻只有一個進程獨享。多線程
可用於不一樣機器間進程的通訊。
套接字包括 3 個屬性:域、類型、 協議。併發
建立 socket 經過 bind 命名綁定端口,listen 建立隊列保存未處理的客戶端請求,accept 等待客戶端的鏈接,connect 服務端鏈接客戶端 socket,close 關閉服務端客戶端的鏈接。異步
stream 和 datagram 的區別:
stream 能提供有序的、可靠的、雙向的、基於鏈接的字節流(TCP),會有拆包粘包問題。
datagram 是無鏈接、不可靠、使用固定大小的緩衝區的數據報服務(UDP),由於基於數據報,且有固定的大小,因此不會有拆包粘包問題。socket
詳細請參考:進程間的五種通訊方式介紹
共享內存:
Java 採用的就是共享內存,內存共享方式必須經過鎖或者 CAS 技術來獲取或者修改共享的變量,看起來比較簡單,可是鎖的使用難度比較大,業務複雜的話還有可能發生死鎖。
消息傳遞:
Actor 模型便是一個異步的、非阻塞的消息傳遞機制。Akka 是對於 Java 的 Actor 模型庫,用於構建高併發、分佈式、可容錯、事件驅動的基於 JVM 的應用。消息傳遞方式就是顯示的經過發送消息來進行線程間通訊,對於大型複雜的系統,可能優點更足。
詳細請參考:Java 內存模型分析
優勢:
充分利用 cpu 的資源,提升 cpu 的使用率,使程序的運行效率提升。
缺點:
有大量的線程會影響性能,操做系統會在線程之間切換,會增長內存的開銷。可能會產生死鎖、存在線程之間的併發問題。
詳細請參考:併發編程挑戰:死鎖與上下文切換
詳細請參考:【SharingObjects】ThreadLocal
java.lang.ThreadLocal.ThreadLocalMap.Entry:
static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { //重點!!!!! super(k); value = v; } }
由於 ThreadLocalMap 中的 key 是弱引用,而 key 指向的對象是 threadLocal,一旦把 threadLocal 實例置爲 null 以後,沒有任何強引用的對象指向 threadLocal 對象,所以 threadLocal 對象會被 Gc 回收,但與之關聯的 value 卻不能被回收,只有當前線程結束後,對應的 map value 纔會被回收。若是當前線程沒結束,可能會致使內存泄漏。
如線程池的場景,在線程中將 threadlocal 置爲 null,但線程沒被銷燬且一直不被使用,就可能會致使內存泄漏
在調用 get、set、remove 方法時,會清除線程 map 中全部 key 爲 null 的 value。因此在不使用 threadLocal 時調用 remove 移除對應的對象。
ThreadPoolExecutor 繼承關係圖:
shutDown 方法執行以後會變成 SHUTDOWN 狀態,沒法接受新任務,隨後等待已提交的任務執行完成。
shutDownNow 方法執行以後變成 STOP 狀態,沒法接受新任務。並對執行中的線程執行 Thread.interrupt()方法。
當任務來時,若是當前的線程數到達核心線程數,會將任務加入阻塞隊列中,若是阻塞隊列滿了以後,會繼續建立線程直到線程數量達到最大線程數,若是線程數量已經達到最大線程數量,且任務隊列滿了以後,會執行拒絕策略。
若是想讓核心線程被回收,可使用 allowCoreThreadTimeOut 參數,若是爲 false(默認值),核心線程即便在空閒時也保持活動狀態。若是 true,核心線程使用 keepAliveTime 來超時等待工做。
java.util.concurrent.Executors 類:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
生成一個固定大小的線程池,此時核心線程數和最大線程數相等,keepAliveTime = 0 ,任務隊列採起 LinkedBlockingQueue 無界隊列(也可設置爲有界隊列)。
適用於爲了知足資源管理需求,而須要限制當前線程數量的應用場景,好比負載比較重的服務器。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
生成只有一個線程的線程池,核心線程數與最大線程數都是 1,keepAliveTime = 0,任務隊列採起 LinkedBlockingQueue,適用於須要保證順序地執行各個任務,而且在任意時間點不會有多個線程是活動的應用場景。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
核心線程數是 0,最大線程數是 int 最大值,keepaliveTime 爲 60 秒,任務隊列採起 SynchronousQueue,適用於執行不少的短時間異步任務的小程序,或者是負載較輕的服務器。
public static ScheduledExecutorService newSingleThreadScheduledExecutor() { return new DelegatedScheduledExecutorService (new ScheduledThreadPoolExecutor(1)); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
定長的線程池,支持週期性任務,最大線程數是 int 最大值,超時時間爲 0,任務隊列使用 DelayedWorkQueue,適用於須要多個後臺執行週期任務,同時爲了知足資源管理需求而須要限制後臺線程的數量的應用場景。
任務執行失敗後,只會影響到當前執行任務的線程,對於整個線程池是沒有影響的。
詳細請參考:ThreadPoolExecutor 線程池任務執行失敗的時候會怎樣
kill -9 pid 操做系統內核級別強行殺死某個進程。
kill -15 pid 發送一個通知,告知應用主動關閉。
ApplicationContext 接受到通知以後,會執行 DisposableBean 中的 destroy 方法。
通常咱們在 destroy 方法中作一些善後邏輯。
調用 shutdown 方法,進行關閉。