什麼是線程?java
進程想要執行任務就須要依賴線程。換句話說,就是進程中的最小執行單位就是線程,而且一個進程中至少有一個線程。web
什麼是多線程?編程
指在同一個進程中同時運行多個線程,如你開啓QQ聊天,能夠開啓多個窗口。安全
提到多線程這裏要說兩個概念,就是串行和並行。 **串行:**實際上是相對於單條線程來執行多個任務來講的,當咱們下載多個文件時,在串行中它是按照必定的順序去進行下載的,串行在時間上是不可能發生重疊的。 **並行:**下載多個文件,開啓多條線程,多個文件同時進行下載,這裏是嚴格意義上的,在同一時刻發生的,並行在時間上是重疊的。服務器
多線程有三大特性:多線程
**原子性:**一個操做或者多個操做,要麼所有執行成功,要麼全都不執行。併發
**可見性:**當多個線程訪問同一個變量時,若是一個線程修改了這個變量的值,其餘線程可以當即看獲得修改後的值。異步
有序性:程序執行的順序按照代碼的前後順序執行。ide
什麼是併發編程?測試
所謂併發編程是指在一臺處理器上「同時」處理多個任務。併發是在同一實體上的多個事件。多個事件在同一時間間隔發生。
併發編程的目的:
- 讓程序充分利用非計算機資源·
- 加快程序響應速度(耗時任務、web服務器)
- 簡化異步時間的處理。
實現多線程的方式:
1) 繼承 Thread
Thread類本質上是實現了Runnable接口的一個實例,代 表一個線程的實例。啓動線程的惟一方法就是經過Thread 類的start()實例方法。
public class MyThread extends Thread { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start();
2) 實現 Runnable 接口
若是本身的類已經extends另外一個類,就沒法直接extends Thread,此時,能夠實現一個Runnable接口
public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } }
3)實現Callable接口經過FutureTask 包裝器來建立 Thread 線程
public class CallableDemo implements Callable<String> { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(1); CallableDemo callableDemo = new CallableDemo(); Future<String> future = executorService.submit(callableDemo); System.out.println(future.get()); executorService.shutdown(); } @Override public String call() throws Exception { int a = 1; int b = 2; System.out.println(a + b); return "執行結果:" + (a + b); } }
線程的狀態:
建立完的線程具備生命週期,從建立到死亡,中間還有一些其餘狀態的變化。
1)新建狀態(New) : 線程對象被建立後,就進入了新建狀態。例如,Thread thread = new Thread()。
2)就緒狀態(Runnable): 也被稱爲「可執行狀態」。線程對象被建立後,其它線程調用了該對象的start()方法,從而來啓動該線程。例如,thread.start()。處於就緒狀態的線程,隨時可能被CPU調度執行。
3)運行狀態(Running) : 線程獲取CPU資源後進行執行。須要注意的是,線程只能從就緒狀態進入到運行狀態。
4)阻塞狀態(Blocked) : 阻塞狀態是線程由於某種緣由讓出CPU資源,暫時中止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的狀況分三種: 等待阻塞 – 經過調用線程的wait()方法,讓線程等待某工做的完成。 同步阻塞 – 線程在獲取synchronized同步鎖失敗(由於鎖被其它線程所佔用),它會進入同步阻塞狀態。 其餘阻塞 – 經過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程從新轉入就緒狀態。
5)死亡狀態(Dead) : 線程順利執行完了或者因異常退出了run()方法,該線程結束生命週期。
線程的經常使用方法:
編號 | 方法 | 說明 |
---|---|---|
1 | public void start() |
使該線程開始執行;Java 虛擬機調用該線程的 run 方法。 |
2 | public void run() |
若是該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;不然,該方法不執行任何操做並返回。 |
3 | public final void setName(String name) |
改變線程名稱,使之與參數 name 相同。 |
4 | public final void setPriority(int priority) |
更改線程的優先級。 |
5 | public final void setDaemon(boolean on) |
將該線程標記爲守護線程或用戶線程。 |
6 | public final void join(long millisec) |
等待該線程終止的時間最長爲 millis 毫秒。 |
7 | public void interrupt() |
中斷線程。 |
8 | public final boolean isAlive() |
測試線程是否處於活動狀態。 |
9 | public static void yield() |
暫停當前正在執行的線程對象,並執行其餘線程。 |
10 | public static void sleep(long millisec) |
在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操做受到系統計時器和調度程序精度和準確性的影響。 |
11 | public static Thread currentThread() |
返回對當前正在執行的線程對象的引用。 |
中止線程:
中止線程是在多線程開發時很重要的技術點,掌握此技術能夠對線程的中止進行有效的處理。
在Java中有如下3種方法能夠終止正在運行的線程:
- 使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止
- 使用stop方法強行終止線程,可是不推薦使用這個方法,由於stop和suspend及resume同樣,都是做廢過時的方法,使用他們可能產生不可預料的結果。
- 使用interrupt方法中斷線程,但這個不會終止一個正在運行的線程,還須要加入一個判斷才能夠完成線程的中止。
多線程注意點:
多線程編程給咱們帶來了不少的優點,如充分利用處理器資源,並行作多件事情,可是在開發多線程應用時,咱們須要注意的問題有不少,好比線程同步、線程死鎖等等。
- 線程安全 在單線程環境下,不加鎖也沒有線程安全和不安全問題,但多線程訪問時,須要線程同步訪問來保證線程安全,如同時有兩個線程,線程A和線程B,對同一個帳號金額進行修改操做,當採用了加鎖機制時,A線程在修改帳號金額,B線程不能進行訪問,直到A線程讀取完,B線程纔可以使用,這樣就不會出現數據不一致或者數據污染。
- 線程死鎖 線程死鎖是指多個線程競爭同一個資源,各自阻塞等待其餘線程持有的鎖,例如: 1.線程1鎖住了A資源,而後嘗試去對B資源加鎖,同時線程2已經鎖住了B資源,再嘗試對A加鎖,爲了彼此都能獲得所需的資源而相互阻塞等待,從而產生了死鎖。 更多java基礎資料等你來拿!!!