1.Jdk的多任務執行框架緩存
JDK提供了一套線程框架Executor來幫助開發者有效的進行線程控制,Executors扮演線程工廠的角色,其建立線程的方法以下框架
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10); //command 就是一個Thread ScheduledFuture<?> scheduledTask = scheduler.scheduleWithFixedDelay(command,5,1, TimeUnit.SECONDS);
若Executors工廠類沒法知足咱們的需求,能夠本身去建立自定義的線程池。自定義線程池的構造方法以下ide
public ThreadPoolExecutor(int corePoolSize,//核心線程數 int maximumPoolSize,//最大線程數 long keepAliveTime,//線程的空閒時間 TimeUnit unit,//給定單元粒度的時間段 BlockingQueue<Runnable> workQueue,//有界、無界隊列 RejectedExecutoionHandler handler//任務拒絕策略 ){.....}
使用什麼隊列對該構造方法來講比較關鍵函數
若是實際線程數>corePoolSize,則將任務添加到緩存隊列 若是緩存隊列已滿 ,總線程<maximumPoolSize, 則建立線程 總線程>maximumPoolSize, 則執行拒絕策略
若有任務須要執行 若是實際線程數<corePoolSize,則建立線程 若是實際線程數>corePoolSize,則將任務添加到緩存隊列, 直到資源耗盡
BlockingQueue<Runnable> queue = //new LinkedBlockingQueue<Runnable>();//無界隊列 new ArrayBlockingQueue<Runnable>(10);//有界隊列 ExecutorService executor = new ThreadPoolExecutor( 5, //core 10, //max 120L, //120s TimeUnit.SECONDS, queue);
JDK的拒絕策略工具
JDK提供的拒絕策略不友好,能夠自定義拒絕策略,實現RejectedExecutionHandler接口(添加日誌等等)性能
public class MyRejected implements RejectedExecutionHandler { public MyRejected(){} @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println("自定義處理"); System.out.println("當前被拒絕的任務爲"+r.toString()); } }
2.Concurrent.util工具類詳解優化
CyclicBarrier
假設每個線程表明一個運動員,當運動員都準備好了,才能一塊兒出發。ui
CyclicBarrier barrier = new CyclicBarrier(3);
CountDownLatch
常常用於監聽某些初始化操做,當初始化執行完畢之後,通知主線程繼續工做this
final CountDownLatch countDownLatch = new CountDownLatch(2);
Callable 和Future使用
Futrue模式費用適合在處理耗時很長的業務邏輯進行使用,能夠有效的減少系統的影響,
提升系統的吞吐量線程
public class UseFuture implements Callable<String>{ private String para; public UseFuture(String para){ this.para = para; } /** * 這裏是真實的業務邏輯,其執行可能很慢 */ @Override public String call() throws Exception { //模擬執行耗時 Thread.sleep(5000); String result = this.para + "處理完成"; return result; } //主控制函數 public static void main(String[] args) throws Exception { String queryStr = "query"; //構造FutureTask,而且傳入須要真正進行業務邏輯處理的類, //該類必定是實現了Callable接口的類 FutureTask<String> future = new FutureTask<String>(new UseFuture(queryStr)); FutureTask<String> future2 = new FutureTask<String>(new UseFuture(queryStr)); //建立一個固定線程的線程池且線程數爲1, ExecutorService executor = Executors.newFixedThreadPool(2); //這裏提交任務future,則開啓線程執行RealData的call()方法執行 //submit和execute的區別: //第一點是submit能夠傳入實現Callable接口的實例對象, // 第二點是submit方法有返回值 Future f1 = executor.submit(future); //單獨啓動一個線程去執行的 Future f2 = executor.submit(future2); System.out.println("請求完畢"); try { //這裏能夠作額外的數據操做,也就是主程序執行其餘業務邏輯 System.out.println("處理實際的業務邏輯..."); Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } //調用獲取數據方法,若是call()方法沒有執行完成,則依然會進行等待 System.out.println("數據:" + future.get()); System.out.println("數據:" + future2.get()); executor.shutdown(); } }
Semaphore信號量
能夠控制系統的流量,拿到線程的信號量則訪問不然等待
經過acquire和release來獲取和釋放線程
final Semaphore semp = new Semaphore(5);
3.鎖的高級深化
Lock and Condition
使用synchronized關鍵字能夠實現線程間的同步互斥工做
使用Lock對象也能夠實現同步互斥
若是多個線程之間須要實現協做 使用Object的wait和nofity,notifyAll
在使用Lock的時候可使用一個新的等待/通知的類Condition 只針對一個具體的鎖
public class UseCondition { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void method1(){ try { lock.lock(); System.out.println("當前線程:" + Thread.currentThread().getName() + "進入等待狀態.."); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + "釋放鎖.."); condition.await(); // Object wait System.out.println("當前線程:" + Thread.currentThread().getName() +"繼續執行..."); condition.signal(); //Object notify } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
ReentrantLock重入鎖
private Lock lock = new ReentrantLock(boolean isFair);//是否爲公平鎖
ReentrantReadWriteLock讀寫鎖
核心是實現讀寫分離 在都多寫少的狀況下 性能高於重入鎖
public class UseReentrantReadWriteLock { private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); private ReadLock readLock = rwLock.readLock(); private WriteLock writeLock = rwLock.writeLock(); public void read(){ try { readLock.lock(); System.out.println("當前線程:" + Thread.currentThread().getName() + "進入..."); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + "退出..."); } catch (Exception e) { e.printStackTrace(); } finally { readLock.unlock(); } } public void write(){ try { writeLock.lock(); System.out.println("當前線程:" + Thread.currentThread().getName() + "進入..."); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + "退出..."); } catch (Exception e) { e.printStackTrace(); } finally { writeLock.unlock(); } } }
鎖的優化