Java天生就是多線程程序,簡單的一個main() 方法的執行,實際上是由main線程和其它的線程共同執行的。固然使用多線程有以下的好處:java
一、利用更多的處理器核心編程
二、更快的響應速度,如將數據一致性不強的操做交給其它的線程去操做多線程
三、更好的編程模型ide
1、線程優先級spa
在線程執行過程當中,線程優先級決定了須要分配處理器資源的多少,從而決定了獲取時間片的多少。如今線程構建時,能夠經過setPriority()方法來修改優先級,默認優先級是5.可是在不一樣的JVM以及操做系統上面,線程的規劃有些不一樣,甚至有些操做系統會忽略對線程優先級的設定,都是採用默認值。操作系統
2、線程狀態線程
線程狀態code
狀態名稱 | 說明 |
NEW | 初始狀態,線程被建立,尚未有調用start()方法 |
RUNNABLE | 運行狀態,java中就緒也屬於運行狀態 |
BLOCKED | 阻塞狀態,表示線程阻塞在進入synchronize修飾的方法或代碼塊(獲取鎖)時的狀態 |
WAITING | 等待狀態,進入該狀態表示當前線程須要等待其餘的線程作出特定動做(通知、中斷)才返回 |
TIME_WAITING | 超時等待,不一樣於WAITING,它是等到指定時間到達自動返回 |
TERMINTED | 終止狀態,表示當前線程執行完成 |
Daemon 是一種支持線程,主要用來支持程序的後臺的調度,因此當Java虛擬機中不存在非Daemon線程(main 線程)時,Java虛擬機將會退出。orm
import java.util.concurrent.TimeUnit; /** * Created by shidong.wu on 2017/10/13. */ public class Daemon { public static void main(String[] args) { Thread thread = new Thread(new DaemonRunner(),"DaemonRunner"); thread.setDaemon(true); thread.start(); } static class DaemonRunner implements Runnable { @Override public void run() { try { TimeUnit.SECONDS.sleep(10); }catch (InterruptedException e) { }finally { System.out.println("Daemon finally"); } } } }
運行上面的程序終端沒有任何輸出,主要是由於非Daemon線程(main線程)運行結束後,Java虛擬機退出了,因此DaemRunner中的finally代碼塊沒有執行。對象
3、中斷
中斷能夠理解爲線程的一個標識位屬性,它標識一個線程是否其它的線程進行的了中斷操做。其它的線程經過調用當前線程的interrupt()方法對其進行中斷操做。線程經過方法isInterrupt()方法來檢查自身是否被中斷來進行響應。拋出InterruptException的線程的,他的中斷標識會被清除。
1、volatile 和synchronized 關鍵字
在前面的已經講過它們的內存含義了,
一、關鍵字volatile用來修飾一個字段(變量),就是告訴程序任意一個線程,對該變量的讀取都要去共享內存中獲取,而都變量的修改必需要同步刷新到共享內存裏,volatile保證了全部線程的對變量的訪問可見性。可是過多的使用volatile,會影響程序的執行效率。
二、關鍵字synchronized用來修飾方法和代碼塊,它主要保證多個線程在同一時刻,只能有一個線程處於synchronized修飾的方法和代碼塊中,其本質是對一個對象監視器(Monitor)的獲取,這個獲取的過程是排他的,同一個時刻,只能有一個線程能獲取大對象的監視器。沒有獲取到監視器的線程進入同步隊列,等待其餘線程釋放鎖。以下圖:
2、等待/通知機制
等待 / 通知機制是指一個線程A調用了對象O的wait()方法,釋放鎖,進入等待狀態,而線程B調用了對象O的notify()或者notifyAll()方法,線程A收到通知後從對象O的wait()方法返回,進而執行後面的操做。
等待 / 通知機制的經典範式,分爲,消費者和生產者;
消費者遵循的規範:
一、獲取對象的鎖
二、若是條件不知足,調用對象的wait()方法,被通知後還要進行條檢查
三、條件知足後執行對應的邏輯
對應的僞代碼:
synchronized(對象){
while(條件不知足){
對象.wait();
}
對應的邏輯;
}
生產者遵循的規範:
一、獲取對象的鎖
二、改變條件
三、通知全部等待在該對象的線程
對此的僞代碼:
synchronized (對象) {
改變條件;
對象.notifyAll();
}
下面咱們就利用上面的等待 / 通知的範式實現一個線程的等待/ 通知的機制;
package com.concurrency; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; /** * Created by shidong.wu on 2017/10/14. */ public class WaitNotify { private static boolean flag = true; private static Object lock = new Object(); public static void main(String[] args) throws Exception{ Thread waitThread = new Thread(new Wait(),"waitThread"); waitThread.start(); TimeUnit.SECONDS.sleep(1); Thread notifyThread = new Thread(new Notify(),"notifyThread"); notifyThread.start(); } static class Wait implements Runnable { public void run() { // 加鎖,lock對象加鎖 synchronized (lock) { while (flag){ // 條件不知足 try { lock.wait(); }catch (InterruptedException e){ } } // 條件知足時,進行完成操做 System.out.println(Thread.currentThread() + new SimpleDateFormat("HH:mm:ss").format(new Date())); } } } static class Notify implements Runnable { public void run() { // 加鎖,lock對象加鎖 synchronized (lock) { lock.notifyAll(); // 通知 flag = false; } } } }
3、join() 使用
若是一個線程A調用了thread.join()表示線程A等待線程thread線程終止以後,才從threa.join()處返回。
4、ThreadLocal 使用
ThreadLocal 是一個線程變量,這個變量是附帶在線程上面的。