Object類相關api(相關的方法一定是當前線程在獲取了對應的鎖對象才能調用,否則會拋出異常)
o.wait() :鎖對象調用該方法使當前線程進入等待狀態,並立刻釋放鎖對象,直到被其他線程喚醒進入等鎖池。
o.wait(long) :鎖對象調用該方法使當前線程進入等待狀態,同時釋放鎖對象。但是超過等待的時間后線程會自動喚醒,或者被其他線程喚醒,並進入等鎖池中。
o.wait(long,int) :和o.wait(long)方法一樣,如果int參數大於0則前面的long數字加1
o.notify():隨機喚醒一個處於等待中的線程(同一個等待阻塞池中)
o.notifyAll():喚醒所有等待中的線程(同一個等待阻塞池中)
Thread類的相關api
Thread.currentThread():返回對當前線程對象的引用
Thread.interrupted():檢測當前線程是否已經中斷(調用該方法后后就將該線程的中斷標志位設置位false,所以連續兩次調用該方法第二次肯定時false)
Thread.sleep(long millis):使當前線程睡眠(不會釋放鎖對象,可以讓其他線程有執行的機會)
Thread.yield():使當前線程放棄cpu的執行權(有可能立刻又被重新選中繼續執行,只可能給優先級更高的線程機會)
t.getId():返回該線程的id
t.getName():返回該線程的名字
t.getPriority():返回該線程的優先級
t.getState():返回該線程的狀態
t.getThreadGroup():返回該線程所屬的線程組
t.interrupt():將該線程中斷(實際並不會中斷,只是將中斷標志設置為true),如果線程正處在sleep(),join(),wait()方法中時(也就是正在阻塞中)調用該方法,該方法會拋出異常。
t.interrupted():檢測該線程是否已經中斷(對中斷標志位不作處理)
t.isAlive():檢測該線程是否還活着
t.isDaemon():檢測該線程是否為守護線程
t.isInterrupted():檢測該線程是否已經中斷
t.join():在a線程中調用b.join(),則a線程阻塞,直到b線程執行完
t.join(long millis):和上面的方法一樣,不過a線程阻塞的時間根據long的大小有關,如果達到設定的阻塞時間,就算b線程沒有執行完,a線程也會被喚醒。
JDK5之后java.uti.concurrent包下面的一些工具類方便開發
1、線程池
①為什么需要線程池? ------- 主要是為了重復利用線程資源,減少系統在創建和銷毀線程上所花的時間和開銷;同時也可以限制資源過多,防止出現OOM或執行效率下降
②如何獲取線程池?
在jdk5及以上版本中,使用java.util.concurrent.Executors類來創建線程池,該類提供了很多靜態方法來創建線程池ExecutorService。
1、Executors.newFixedThreadPool(int) 創建一個最大規模固定的線程池,如果當前線程不夠用且沒有超過線程池限制數量,則創建新的線程。如果線程池已滿,則會將任務放入等待隊列。
2、Executors.newCachedThreadPool 創建一個最大規模可為Integer.MAX_VALUE 的可緩存的線程池。如果當前線程不夠用就增加線程池中的線程數,如果當前線程池中線程過多,則會回收空的線程。
3、Executors.newSingleThreadExecutor創建一個單線程的線程池,確保任務串行
4、Executors.newScheduledThreadPool 創建一個固定大小的線程池,以延遲或者固定周期的方式執行,類似於定時器。
③執行任務和關閉線程池
e.execute(Runnable r) :執行任務無返回值
e.submit(Runnable r) :執行任務返回Future<?> ,實際上是null
e.submit(Runnable r,T result) : 執行任務返回Future<T>
e.submit(Callable c) :執行返回Future<?>
e.invokeAny(Collection<? extends Callable<T> > c):隨機執行集合中的一個任務,返回T。如果其中一個任務執行結束(或者拋了一個異常),其他 Callable 將被取消。
e.invokeAll(Collection<? extends Callable<T> > c):執行集合中所有的任務,返回List<Future<T>>
e.shutdown():調用該方法后線程池立刻變成shutdown狀態,不能再往線程池中增加新的任務否則將會拋出RejectedExecutionException異常,等所有進入隊列的任務都執行完畢后關閉線程池
e.shutdownNow():調用該方法后,線程池立刻變成stop狀態,停止接受新的任務,並且試圖停止所有正在執行的任務(使用的是Thread.interrupt()方法,不一定能中斷正在執行的線程),不會執行等待隊列中的任務,然后關閉線程池。
public class Test7 { public static void main(String[] args) throws InterruptedException, ExecutionException { //獲取當前系統cpu的數目 int availableProcessors = Runtime.getRuntime().availableProcessors(); ExecutorService fixedThreadPool = Executors.newFixedThreadPool(availableProcessors); fixedThreadPool.execute(new MyThread7()); fixedThreadPool.shutdown(); ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); Future<?> future = singleThreadExecutor.submit(new MyThread7()); Future<?> future2 = singleThreadExecutor.submit(new MyThread8()); System.out.println("future: "+future.get()); System.out.println("future2: "+future2.get()); singleThreadExecutor.shutdown(); ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); String result = "這是result"; Future<String> submit = cachedThreadPool.submit(new MyThread7(),result); System.out.println("..."+submit.get()); cachedThreadPool.shutdown(); ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(availableProcessors); //初始延遲3秒鍾,只執行一次 scheduledThreadPool.schedule(new MyThread8(), 3, TimeUnit.SECONDS ); //初始延遲2秒中,每5秒執行一次 scheduledThreadPool.scheduleWithFixedDelay(new FixedDelay(), 2, 5, TimeUnit.SECONDS); //初始延遲1秒鍾,每4秒中執行一次 scheduledThreadPool.scheduleAtFixedRate(new FixedRate(), 1, 4, TimeUnit.SECONDS); Thread.sleep(20000); scheduledThreadPool.shutdown(); } } class MyThread7 implements Runnable{ @Override public void run() { System.out.println("執行代碼:"+System.currentTimeMillis()/1000); } } class MyThread8 implements Callable<String>{ @Override public String call() { System.out.println("執行代碼:"+System.currentTimeMillis()/1000); return "執行完成"; } } class FixedDelay implements Runnable{ @Override public void run() { System.out.println("FixedDelay執行代碼:"+System.currentTimeMillis()/1000); } } class FixedRate implements Runnable{ @Override public void run() { System.out.println("FixedRate執行代碼:"+System.currentTimeMillis()/1000); } }
執行結果:
執行代碼:1523348201
執行代碼:1523348201
future: null
執行代碼:1523348201
future2: 執行完成
執行代碼:1523348201
...這是result
FixedRate執行代碼:1523348202
FixedDelay執行代碼:1523348203
執行代碼:1523348204
FixedRate執行代碼:1523348206
FixedDelay執行代碼:1523348208
FixedRate執行代碼:1523348210
FixedDelay執行代碼:1523348213
FixedRate執行代碼:1523348214
FixedRate執行代碼:1523348218
FixedDelay執行代碼:1523348218
④ThreadPoolExecutor學習
其實通過源碼可知newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor 三種線程池的創建都是通過調用如下的方法來創建的。
public ThreadPoolExecutor(int corePoolSize,//核心線程池大小 int maximumPoolSize,//最大線程池大小 long keepAliveTime,//線程執行完成后在線程池中的緩存時間,也就是線程空閑多長時間后會被回收 TimeUnit unit,//時間單位TimeUnit.SECONDS BlockingQueue<Runnable> workQueue,//線程緩沖隊列,當線程池線程運行超過一定線程時並滿足一定的條件,待運行的線程會放入到這個隊列 ThreadFactory threadFactory,//線程工廠,用來創建線程 RejectedExecutionHandler handler//當緩沖隊列也放不下線程時的拒絕策略
){
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
線程池總結:
ThreadPoolExecutor對象初始化時,不創建任何執行線程,當有新任務進來時,才會創建線程來執行任務。當目前執行線程的總數小於核心線程大小時,所有新加入的任務,都會創建新線程來處理。當目前執行線程的總數大於或等於核心線程時,所有新加入的任務,都放入任務緩存隊列中。當目前執行線程的總數大於或等於核心線程,並且緩存隊列已滿,同時此時線程總數小於線程池的最大規模,那么創建新線程,協助處理新的任務。當所有線程都在執行,線程池大小已經達到上限,並且緩存隊列已滿時,就rejectHandler拒絕新的任務。
2、BlockingQueue:阻塞隊列。
下面是接口中一些常見的方法:BlockingQueue中不能插入null值,否則會拋出NullPointerException。
①ArrayBlockingQueue:有界的阻塞隊列,其內部是通過數組實現,
②DelayQueue:無界的阻塞延時隊列,加入該隊列的元素需要實現Delayed接口,實現該接口的元素會有一個過期時間,只有過期的元素才能被取出。隊列中元素會根據過期的先后順序排序
③LinkedBlockingQueue:通過鏈式結構對元素進行儲存,該鏈式結構可以設置存儲上限,如果沒有則用Integer.MAX_VALUE作為上限。
④PriorityBlockingQueue:優先級隊列,加入該隊列的元素必須實現Comparable接口,因為隊列會根據compare()方法來對元素進行排序。
⑤SynchronousQueue:同步隊列,該隊列只能容納一個元素,如果隊列中已經有元素,則新加入的元素會阻塞。
⑥BlockingDeque:阻塞雙端隊列,可以將元素放入隊列兩端或從兩端取出元素,該接口繼承了BlockingQueue,實現類為LinkedBlockingDeque。
3、java.util.concurrent.ConcurrentHashMap:和java.util.HashTable類似,但是ConcurrentHashMap擁有更好的並發性能。它在寫入數據的時候不會將整個ConcurrentHashMap鎖住,而是將寫入的部分鎖住。
4、CountDownLatch:閉鎖是一個並發構造,它允許一個或多個線程等待一系列的操作完成。CountDownLatch初始化時需要給定一個數量,閉鎖調用await()方法可以使線程進入等待狀態,該閉鎖每調用一次countDown()就會將數量減1,當數量減為0后,所有的等待線程就會被喚醒。
4、java.util.concurrent.CyclicBarrier:柵欄是一種類的同步機制,可以實現所有線程運行到某處后等待(通過調用await()方法),直到滿足了所需的數量,才會一起釋放去繼續執行。當然也可以設定等待時間,那樣即使沒有達到數量也會繼續執行。類似於約人一起去玩,先在某個地方一起集合,然后一起去。這是可以重復使用的。
5.每次CyclicBarrier都支持柵欄行動,當最后一個線程都運行到柵欄時,就會執行該行動。CyclicBarrier行動就是一個線程。
6、交換機java.util.concurrent.Exchanger:表示兩個線程可以交換一類對象的匯合點,通過exchange(o)方法來交換對象。
7、信號量java.util.concurrent.Semaphore:它是一個計數信號量,主要用於防止超過N個線程同時執行一塊代碼,或者進行兩個線程之間發送信號。它主要有兩個方法,require()和release()分別用來獲取許可和釋放許可。
8、java.util.concurrent.locks.Lock:一個類似於 synchronized 塊的線程同步機制。但是 Lock 比 synchronized 塊更加靈活、精細。實現類java.util.concurrent.locks.ReentrantLock
9、java.util.concurrent.locks.ReadWriteLock :讀寫鎖,它能夠允許多個線程在同一時間對某特定資源進行讀取,但同一時間內只能有一個線程對其進行寫入。實現類 java.util.concurrent.locks.ReentrantReadWriteLock
10、ForkJoinPool:其作用和ExecutorService差不多,但是其可以對任務進行分叉和合並
11、AtomicBoolean、AtomicInteger、AtomicLong :數據具有原子性,並且增加了一些操作的方法。
12、AtomicReference提供了一個可以被原子性讀和寫的對象引用變量