做者:Greyhtml
原文地址:Java多線程學習筆記java
源碼: Githubgit
線程就是輕量級進程,是程序執行的最小單位。github
多進程的方式也能夠實現併發,爲何咱們要使用多線程?編程
從底層角度上看,CPU主要由以下三部分組成,分別是:網絡
T1線程在執行的時候,將T1線程的指令放在PC,數據放在Registers,假設此時要切換成T2線程,T1線程的指令和數據放cache,而後把T2線程的指令放PC,數據放Registers,執行T2線程便可。多線程
以上的整個過程是經過操做系統來調度的,且線程的調度是要消耗資源的,因此,線程不是設置越多越好。併發
有意義,由於線程的操做中可能有不消耗CPU的操做,好比:等待網絡的傳輸,或者線程sleep,此時就可讓出CPU去執行其餘線程。能夠充分利用CPU資源。ide
不是,由於線程切換要消耗資源。高併發
示例:
單線程和多線程來累加1億個數。-> CountSum.java
和CPU的核數有關
最好是經過壓測來評估。經過profiler性能分析工具jProfiler,或者Arthas
公式
N = Ncpu * Ucpu * (1 + W/C)
其中:
Ncpu是處理器的核的數目,能夠經過Runtime.getRuntime().availableProcessors() 獲得
Ucpu是指望的CPU利用率(該值應該介於0和1之間)
W/C是等待時間和計算時間的比率。
具體示例可見:HelloThread.java
線程剛剛建立,尚未啓動
即:剛剛New Thread的時候,尚未調用start方法時候,就是這個狀態
可運行狀態,由線程調度器能夠安排執行,包括如下兩種狀況:
- READY
- RUNNING
READY和RUNNING經過yield來切換
等待被喚醒
隔一段時間後自動喚醒
被阻塞,正在等待鎖
只有在synchronized的時候在會進入BLOCKED狀態
線程執行完畢後,是這個狀態
打斷某個線程(設置標誌位)
查詢某線程是否被打斷過(查詢標誌位)
查詢當前線程是否被打斷過,並重置打斷標誌位
示例代碼:ThreadInterrupt.java
以上兩種方式都不建議使用, 由於會產生數據不一致的問題,由於會釋放全部的鎖。
若是不依賴循環的具體次數或者中間狀態, 能夠經過設置標誌位的方式來控制
public class ThreadFinished { private static volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { // 推薦方式:設置標誌位 Thread t3 = new Thread(() -> { long i = 0L; while (flag) { i++; } System.out.println("count sum i = " + i); }); t3.start(); TimeUnit.SECONDS.sleep(1); flag = false; } }
若是要依賴循環的具體次數或者中間狀態, 則能夠用interrupt方式
public class ThreadFinished { public static void main(String[] args) throws InterruptedException { // 推薦方式:使用interrupt Thread t4 = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { } System.out.println("t4 end"); }); t4.start(); TimeUnit.SECONDS.sleep(1); t4.interrupt(); } }
示例代碼: ThreadFinished.java