java基礎鞏固筆記(5)-多線程之線程併發庫

java基礎鞏固筆記(5)-多線程之線程併發庫

標籤: javahtml


[TOC]java


本文主要概述java.util.concurrent包下的相關類和使用方法git

Package java.util.concurrentgithub

原子性操做類

java.util.concurrent.atomic包下的類:api

Package java.util.concurrent.atomic緩存

線程池

java.util.concurrent:Class Executors多線程

經常使用線程池

幾種經常使用的的生成線程池的方法:併發

  • newCachedThreadPool
  • newFixedThreadPool
  • newScheduledThreadPool
  • newSingleThreadExecutor
  • newSingleThreadScheduledExecutor

例子:newFixedThreadPooloracle

ExecutorService threadPool = Executors.newFixedThreadPool(3);
for(int i=0;i<10;i++){
    threadPool.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
}

單線程newSingleThreadExecutor可用於重啓ide

用線程池啓動定時器

例子:相似Timer的定時執行

Executors.newScheduledThreadPool(3).scheduleAtFixedRate(
            new Runnable() {
                @Override
                public void run() {
                    System.out.println("ScheduledThreadPool "+Thread.currentThread().getName());
                }
            },3,1, TimeUnit.SECONDS
    );

Callable&Future

ExecutorServiceExecutor的基礎上增長了一些方法,其中有兩個核心的方法:

  • Future<?> submit(Runnable task)
  • <T> Future<T> submit(Callable<T> task)

這兩個方法都是向線程池中提交任務,它們的區別在於Runnable在執行完畢後沒有結果,Callable執行完畢後有一個結果。這在多個線程中傳遞狀態和結果是很是有用的。另外他們的相同點在於都返回一個Future對象。Future對象能夠阻塞線程直到運行完畢(獲取結果,若是有的話),也能夠取消任務執行,固然也可以檢測任務是否被取消或者是否執行完畢。

Lock&Condition

Lock

Lock功能相似傳統多線程技術裏的synchronized,實現線程互斥,但更加面向對象。將須要互斥的代碼片斷放到lock.lock();lock.unlock();之間。

例子

class A{
    private Lock lock = new ReentrantLock();
    
    public void function(){
        lock.lock();
        try{
            //功能代碼
        }finally{
            lock.unlock();
        }
    }
}
  • 讀寫鎖

java.util.concurrent.locks:Class ReentrantReadWriteLock

javaDoc文檔讀寫鎖例子,緩存:

class CachedData {
   Object data;
   volatile boolean cacheValid;
   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {
     rwl.readLock().lock();
     if (!cacheValid) {
       // Must release read lock before acquiring write lock
       rwl.readLock().unlock();
       rwl.writeLock().lock();
       try {
         // Recheck state because another thread might have
         // acquired write lock and changed state before we did.
         if (!cacheValid) {
           data = ...
           cacheValid = true;
         }
         // Downgrade by acquiring read lock before releasing write lock
         rwl.readLock().lock();
       } finally {
         rwl.writeLock().unlock(); // Unlock write, still hold read
       }
     }

     try {
       use(data);
     } finally {
       rwl.readLock().unlock();
     }
   }
 }

重點注意在釋放寫鎖前加讀鎖那部分代碼,註釋爲 // Downgrade by acquiring read lock before releasing write lock。本身掛了寫鎖,再掛讀鎖是能夠的,這面涉及的技巧之後再研究。

Condition

Condition相似於傳統多線程技術中的Object.waitObject.notify,實現線程間同步。

javaDoc文檔例子,可阻塞隊列

class BoundedBuffer例子

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)
         notFull.await();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }

使用了兩個condition

同步工具

  • Semaphore

相似佔坑

  • CyclicBarrier

階段性使進度一致

  • CountDownLatch

一人通知多人/多人通知一人

  • Exchanger

線程間數據交換,都到達則天然交換

參考資料


做者@brianway更多文章:我的網站 | CSDN | oschina

相關文章
相關標籤/搜索