java多線程與併發編程

什麼是線程?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基礎資料等你來拿!!!
相關文章
相關標籤/搜索