Thread 類本質上是實現了 Runnable 接口的一個實例,表明一個線程的實例。 啓動線程的惟一方法就是經過 Thread 類的 start()實例方法。 start()方法是一個 native 方法,它將啓動一個新線程,並執行 run()方法。數據庫
public class MyThread extends Thread { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); myThread1.start();
若是本身的類已經 extends 另外一個類,就沒法直接 extends Thread,此時,能夠實現一個Runnable 接口。編程
public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } }
有返回值的任務必須實現 Callable 接口,相似的,無返回值的任務必須 Runnable 接口。執行Callable 任務後,能夠獲取一個 Future 的對象,在該對象上調用 get 就能夠獲取到 Callable 任務返回的 Object 了。多線程
public class callableTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newFixedThreadPool(10); //建立一個Callable,3秒後返回String類型 Callable myCallable = new Callable() { @Override public String call() throws Exception { // Thread.sleep(3000); System.out.println("calld方法執行了"); return "call方法返回值"; } }; List<Future> list = new ArrayList<Future>(); for (int i = 0; i < 10; i++) { Future future = executor.submit(myCallable); list.add(future); }
當線程被建立並啓動之後,它既不是一啓動就進入了執行狀態,也不是一直處於執行狀態。
在線程的生命週期中,它要通過新建(New)、就緒(Runnable)、運行(Running)、阻塞(Blocked)和死亡(Dead)5 種狀態。尤爲是當線程啓動之後,它不可能一直"霸佔"着 CPU 獨自運行,因此 CPU 須要在多條線程之間切換,因而線程狀態也會屢次在運行、阻塞之間切換。jvm
當程序使用 new 關鍵字建立了一個線程以後,該線程就處於新建狀態,此時僅由 JVM 爲其分配內存,並初始化其成員變量的值。ide
當線程對象調用了 start()方法以後,該線程處於就緒狀態。 Java 虛擬機會爲其建立方法調用棧和程序計數器,等待調度運行。工具
若是處於就緒狀態的線程得到了 CPU,開始執行 run()方法的線程執行體,則該線程處於運行狀態。this
阻塞狀態是指線程由於某種緣由放棄了 cpu 使用權,也即讓出了 cpu timeslice,暫時中止運行。spa
直到線程進入可運行(runnable)狀態,纔有機會再次得到 cpu timeslice 轉到運行(running)狀態。阻塞的狀況分三種:線程
運行(running)的線程執行 o.wait()方法, JVM 會把該線程放入等待隊列(waitting queue)中。code
運行(running)的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則 JVM 會把該線程放入鎖池(lock pool)中。
運行(running)的線程執行 Thread.sleep(long ms)或 t.join()方法,或者發出了 I/O 請求時,JVM 會把該線程置爲阻塞狀態。當 sleep()狀態超時、 join()等待線程終止或者超時、或者 I/O處理完畢時,線程從新轉入可運行(runnable)狀態。
線程會如下面三種方式結束,結束後就是死亡狀態。
1.正常結束
run()或 call()方法執行完成,線程正常結束。
2.異常結束
線程拋出一個未捕獲的 Exception 或 Error。
3.調用 stop
直接調用該線程的 stop()方法來結束該線程—該方法一般容易致使死鎖,不推薦使用。
若是有一個對象在被多個線程同時競爭,那麼判斷對象是否有鎖,若是有鎖,那麼會先支持偏向鎖,就是說當前已經得到鎖的線程會優先拿到鎖(markword區記錄了偏向線程id)。那麼拿不到鎖的線程,就會升級鎖,變成CAS synchronized樂觀鎖,會進行一段時間的循環自旋不斷嘗試獲取鎖,當自旋到必定次數後,會再次升級成synchronized重量級鎖。
鎖方法會鎖住this,鎖靜態方法會鎖住class對象.鎖代碼塊能夠指定任意對象做爲鎖.
同步代碼塊可能會涉及到一個重入過程,synchronized不會說由於重入去不斷重複獲取鎖釋放鎖的過程,而是用mointer每次重入去作一個計數器加一操做,在釋放鎖的過程當中也會逐步將計算器清零。而後讓其餘線程從block阻塞狀態變成runnable狀態去競爭這個鎖。
synchronized不用手動編程,他是一個jvm關鍵字,我也不用關心他鎖釋放的一個過程,直接用就好了,而reentrantlock他是一個類,須要手動lock,配合try catch finally中去作一個鎖釋放操做
線程和數據庫鏈接這些資源都是很是寶貴的資源。那麼每次須要的時候建立,不須要的時候銷燬,是很是浪費資源的。Java 裏面線程池的頂級接口是 Executor,可是嚴格意義上講 Executor 並非一個線程池,而只是一個執行線程的工具。真正的線程池接口是 ExecutorService。
一個線程池創建後,若是沒有預加載任務,他一開始的核心線程數爲0,當一個新任務被提交時,會創建一個核心線程去執行任務,若是一直來任務,而先前創建的核心線程都在忙,那麼就會一直創建核心線程直到到達最大核心線程數。
但核心線程數最大,並且都在執行任務時,後來的任務會被放到blockingqueue(阻塞隊列裏),若是阻塞隊列也滿了,就會去創建新線程,此時的線程叫非核心線程,當整個線程池的線程數達到最大,他也有一個max access時,會觸發拒絕策略。
AbortPolicy 停止策略
會直接拋出異常來執行停止任務執行拒絕
DiscardPolicy 拋棄策略
他會丟棄不執行多餘的任務來執行拒絕
DIscardOldestPolicy
會丟棄最先你未執行的任務
callrunpolicy
在多線程環境下