進程:進程指的是一段正在運行的程序
線程:一個程序運行中能夠執行多個任務,任務就稱之爲線程。
進程能夠有多個線程,各個線程之間共享程序的內存空間面試
每一個進程有本身獨立的地址空間,多併發請求,爲每個請求建立一個進程,致使系統開銷、用戶請求效率低算法
每一個進程有用本身獨有的變量,線程共享數據,線程之間的通訊相比於進程之間的通訊更加有效,更加容易
線程相比於進程建立/銷燬開銷 更小
進程是資源分配的最小單位,線程是CPU調度的最小單位
多進程程序更加健壯,多線程程序只要有一個線程掛掉,對其共享資源的其餘線程也回產生影響
若是追求速度,追求系統穩定選擇線程;若是頻繁的建立和銷燬,選擇線程;spring
說完線程的基本知識,那麼久要談談在應用中,咱們應該如何建立線程,實際應用中建立線程主要有如下四種方法,以下:數據庫
class MyThread extends Thread{ @Override public void run() { while(true){ System.out.println("eat food"); } } } public class TestDemo1 { public static void main(String[] args) { //邊吃飯邊看電視 //建立子線程對象 Thread thread = new MyThread(); //啓動吃飯的thread thread.run(); //main線程 while(true){ System.out.println("watch Tv"); } } }
class MyRunnable implements Runnable{ @Override public void run() { while(true){ System.out.println("eat food"); } } } public class TestDemo1 { public static void main(String[] args) { //實現runnable接口 建立子線程 建立子線程對象 Thread thread = new Thread(new MyRunnable()); thread.start(); } }
//匿名內部類 建立線程 new Thread(){ @Override public void run() { System.out.println("thread 0"); } }.start();
利用Callable建立時,步驟較爲複雜,具體以下:
a.建立Callable接口的實現類,重寫call方法
b.建立Callable實現類的實例,使用FutureTask包裝該實例
c.將FutureTask實例做爲參數建立線程對象
d.啓動該線程
e.調用FutureTask的get方法獲取子線程的執行結果設計模式
class MyCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { int sum = 0; for(int i=0; i<10000; i++){ sum += i; } return sum; } } public class TestDemo1 { public static void main(String[] args) { //建立Callable接口的實現類 重寫call 方法 //建立Callable實現類的實例 Callable<Integer> callableTask = new MyCallable(); //使用FutureTask包裝實例 FutureTask<Integer> task = new FutureTask<>(callableTask); //Future實例做爲參數建立線程對象 Thread thread = new Thread(task); //啓動該線程 thread.start(); //調用FutureTask的get 方法獲取子線程的執行結果 try { Integer integer = task.get(); System.out.println("result"+integer); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }
可能有人會思考,這裏一樣使用Runable和Callable接口來建立線程,那麼這二者各有什麼不一樣呢?能想到這,可謂是很用心啦,這也是這裏的一個面試考點吶!!!
Runable 接口和 Callable 接口的區別?
緩存
這裏就簡單說一下二者的區別,可是僅僅單獨比較兩個接口的區別實際意義並不大,而且也不是很全面,以後會
詳細的分析兩個接口的區別,在更深層次上去理解兩個接口。你們繼續關注吖!數據結構
線程的生命週期主要包括如下六種狀態:新建狀態、就緒狀態、阻塞狀態、等待狀態、睡眠狀態、終止狀態。多線程
一、new() :新建狀態 new關鍵字建立一個線程對象,它並非出於執行狀態 並未執行START方法啓動線程 二、runnable() :就緒狀態 等待被執行 線程對象調用START方法,纔是JVM中真正建立了一個線程, 建立好的線程並非一經啓動,就會當即執行。該狀態的全部線程會位於就緒線程池中,等待當前操做系統的資源,例如CPU, 得到CPU的使用權。 三、blocked(): 阻塞狀態 等待一個監視器鎖進入同步代碼塊或者同步方法,代碼塊和方法指某一時刻 只可以有一個線程去執行,其餘線程只能等待。 四、Waiting(): 等待狀態 Object.wait()/Thread.join()/LockSupport.park() 都會使得當前從Runnable 轉換爲Waiting 狀態 調用waiting() 會釋放monitor Lock 五、TimeWaiting():睡眠狀態 調用Object.wait(long miles)/Thread.sleep(long miles)/LockSupport.parkNano()/LockSupport.parkUntile() 六、Terminated():終止狀態 是一個線程的最終狀態 線程若是進入此狀態,意味着該線程結束。
簡單瞭解線程的生命週期以後,那咱們繼續學習線程六狀態之間的轉換:併發
經常使用方法解析分佈式
啓動一個線程,將線程添加到線程組中,線程狀態會從New 狀態轉換到Runnable 狀態,而後獲取CPU以後進入Running狀態執行run();
靜態方法 ,存在兩個重載函數
public static native void sleep(long millis) public static void sleep(long millis, int nanos)
做用:sleep()方法使得當前線程進入睡眠狀態並指定休眠時間,暫停執行;
sleep()方法不會釋放Monitor Lock 使用權;
JDK1.5以後,引入枚舉類TimeUnit ,其對sleep進行封裝 直接使用從而省去時間換算的步驟,不用將時間轉爲ms,更加的方便使用。
public static native void yield();
做用: 提醒CPU調度器 ,我當前的線程願意放棄當前的CPU資源(屬於啓發式方法),若是當前CPU資源不緊張,會忽略這種提醒。
yield()方法不會釋放Monitor Lock 使用權;
join() 一直等待 join(long millis) 等待指定毫秒數 join(long millis, int nanos) 等待指定毫秒數
含義:在線程B中join某個線程A,會使得B線程進入等待,直到線程A結束生命週期,或者達到給定的時間,在這給定時間期間線程B會處於等待狀態.
調用某個對象的wait()方法可讓當前線程阻塞
調用當前對象notify/notifyAll纔可以喚醒這個對象所在的線程。
將鎖對象等待池中全部線程移動到鎖標誌等待池中。
注意:使用這三個方法須要讓當前線程擁有當前對象的monitor lock
每一個Java線程都會有一箇中斷狀態位,程序能夠檢測這個中斷狀態位判讀線程是否執行結束。有如下三種方法:
interrupt()
public void interrupt() 由線程對象調用,將中斷位置置爲true
public void interrupt();
以下方法可以使得當前線程進入阻塞狀態,調用interrupt方法能夠打斷阻塞,所以這種方法被稱之爲可中斷方法
Object.wait()/wait(long) Thread.sleep(long)/TimUnit.XXX.sleep(long) Thread.join()/Thread.join(long)
若是一個線程被interrupt,設置interrupt flag;若是當前線程正在執行可中斷方法,調用interrupt方法,反而致使interrupt flag被清除.
isInterrupted
public boolean isInterrupted();
實例方法,判斷當前線程的中斷狀態位是否爲true,判斷進程是否被中斷。
interrupted()
public static boolean interrupted();
靜態方法,調用interrupted會擦除中斷狀態位的標識,判斷進程是否被中斷
interrupted和isInterrupted方法的區別:
1)interrupted()是靜態方法,isInterrupted()是實例方法;
2)interrupted()會清空線程中斷狀態,isInterrupted()不會清空線程中斷狀態。
歡迎關注公衆號:前程有光,領取一線大廠Java面試題總結+各知識點學習思惟導+一份300頁pdf文檔的Java核心知識點總結! 這些資料的內容都是面試時面試官必問的知識點,篇章包括了不少知識點,其中包括了有基礎知識、Java集合、JVM、多線程併發、spring原理、微服務、Netty 與RPC 、Kafka、日記、設計模式、Java算法、數據庫、Zookeeper、分佈式緩存、數據結構等等。