java多線程api


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提供了一個可以被原子性讀和寫的對象引用變量

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM