學習能夠參考:源碼+官方文檔 進行學習java
文檔地址:https://docs.oracle.com/javase/8/docs/api/面試
首先咱們看看什麼是JUC算法
其次咱們看看JUC都有哪些東西編程
因而咱們能夠總結下JUC能夠分爲五大類api
一、同步工具類多線程
二、lock類併發
三、原子類oracle
四、集合相關類框架
五、Executor框架相關類ide
線程、進程,若是不能使用一句話說出來,說明技術不紮實!
進程:一個程序,QQ.exe Music.exe 程序的集合;
一個進程每每能夠包含多個線程,至少包含一個!
Java默認有幾個線程? 2 個 mian、GC
線程:開了一個進程 Typora,寫字,自動保存(線程負責的) 對於Java而言:Thread、Runnable、Callable
Java 真的能夠開啓線程嗎? 開不了,咱們看看源碼
public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } //本地方法,底層C++,java 無是沒法直接操做硬件的 private native void start0();
併發、並行
併發編程:併發、並行
併發(多線程操做同一個資源)
CPU 一核 ,模擬出來多條線程,天下武功,惟快不破,快速交替
並行(多我的一塊兒行走)
CPU 多核 ,多個線程能夠同時執行; 線程池
public class Test1 { public static void main(String[] args) { // 獲取cpu的核數 // CPU 密集型,IO密集型 System.out.println(Runtime.getRuntime().availableProcessors()); } }
併發編程的本質:充分利用CPU的資源
全部的公司都很看重!
企業,掙錢=> 提升效率,裁人,找一個厲害的人頂替三個不怎麼樣的人;
人員(減) 、技術成本(高)
線程有幾個狀態
public enum State { //新建 NEW, /運行 RUNNABLE, //阻塞 BLOCKED, //等待 WAITING, //超時等待 TIMED_WAITING, //終止 TERMINATED; }
wait/sleep區別
一、來自不一樣的類 wait => Object
sleep => Thread
二、關於鎖的釋放 wait 會釋放鎖,sleep 睡覺了,抱着鎖睡覺,不會釋放!
三、使用的範圍是不一樣: wait必須在同步代碼塊中,sleep能夠在任何地方睡
傳統Synchronized
/** * 真正的多線程開發,公司中的開發,下降耦合性 * 線程就是一個單獨的資源類,沒有任何附屬的操做! * 一、 屬性、方法 */ public class SaleTicketDemo01 { public static void main(String[] args) { // 併發:多線程操做同一個資源類, 把資源類丟入線程 Ticket ticket = new Ticket(); // @FunctionalInterface 函數式接口,jdk1.8 lambda表達式 (參數)->{ 代碼 } new Thread(()->{ for (int i = 1; i < 40 ; i++) { ticket.sale(); } },"A").start(); new Thread(()->{ for (int i = 1; i < 40 ; i++) { ticket.sale(); } },"B").start(); new Thread(()->{ for (int i = 1; i < 40 ; i++) { ticket.sale(); } },"C").start(); } } // 資源類 OOP class Ticket { // 屬性、方法 private int number = 30; // 賣票的方式 // synchronized 本質: 隊列,鎖 public synchronized void sale(){ if (number>0){ System.out.println(Thread.currentThread().getName()+"賣出了"+(number--)+"票,剩餘:"+number); } } }
Lock接口
實現類:可重入鎖、讀鎖、寫鎖
public ReentrantLock() { sync = new NonfairSync();//非公平鎖(默認) } /** * Creates an instance of {@code ReentrantLock} with the * given fairness policy. * * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantLock(boolean fair) {//公平鎖 sync = fair ? new FairSync() : new NonfairSync(); }
公平鎖:十分公平:能夠先來後到
非公平鎖:十分不公平:能夠插隊 (默認)
案例代碼:
public class SaleTicketDemo02 { public static void main(String[] args) { // 併發:多線程操做同一個資源類, 把資源類丟入線程 Ticket2 ticket = new Ticket2(); // @FunctionalInterface 函數式接口,jdk1.8 lambda表達式 (參數)->{ 代碼 } new Thread(()->{for (int i = 1; i < 40 ; i++) ticket.sale();},"A").start(); new Thread(()->{for (int i = 1; i < 40 ; i++) ticket.sale();},"B").start(); new Thread(()->{for (int i = 1; i < 40 ; i++) ticket.sale();},"C").start(); } } // Lock三部曲 // 一、 new ReentrantLock(); // 二、 lock.lock(); // 加鎖 // 三、 finally=> lock.unlock(); // 解鎖 class Ticket2 { // 屬性、方法 private int number = 30; Lock lock = new ReentrantLock(); public void sale(){ lock.lock(); // 加鎖 try { // 業務代碼 if (number>0){ System.out.println(Thread.currentThread().getName()+"賣出了"+(number--)+"票,剩餘:"+number); } } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); // 解鎖 } } }
Synchronized 和 Lock 區別
一、Synchronized 內置的Java關鍵字, Lock 是一個Java類
二、Synchronized 沒法判斷獲取鎖的狀態,Lock 能夠判斷是否獲取到了鎖
三、Synchronized 會自動釋放鎖,lock 必需要手動釋放鎖!若是不釋放鎖,死鎖
四、Synchronized 線程 1(得到鎖,阻塞)、線程2(等待,傻傻的等);Lock鎖就不必定會等待下 去;
五、Synchronized 可重入鎖,不能夠中斷的,非公平;Lock ,可重入鎖,能夠 判斷鎖,非公平(能夠 本身設置);
六、Synchronized 適合鎖少許的代碼同步問題,Lock 適合鎖大量的同步代碼!
鎖是什麼呢,如何判斷鎖是誰?
面試的:單例模式、排序算法、生產者和消費者、死鎖
生產者和消費者問題 Synchronized 版
/** * 線程之間的通訊問題:生產者和消費者問題! 等待喚醒,通知喚醒 * 線程交替執行 A B 操做同一個變量 num = 0 * A num+1 * B num-1 */ public class A { public static void main(String[] args) { Data data = new Data(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"C").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"D").start(); } } // 判斷等待,業務,通知 class Data{ // 數字 資源類 private int number = 0; //+1 public synchronized void increment() throws InterruptedException { if (number!=0){ //0 // 等待 this.wait(); } number++; System.out.println(Thread.currentThread().getName()+"=>"+number); // 通知其餘線程,我+1完畢了 this.notifyAll(); } //-1 public synchronized void decrement() throws InterruptedException { if (number==0){ // 1 // 等待 this.wait(); } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); // 通知其餘線程,我-1完畢了 this.notifyAll(); } }
問題存在,A B C D 4 個線程! 虛假喚醒,注意要把 if 判斷改成 while ,由於 if 只會判斷一次!
JUC版的生產者和消費者問題
經過Lock找到Condition
代碼實現:
public class B { public static void main(String[] args) { Data2 data = new Data2(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"C").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"D").start(); } } // 判斷等待,業務,通知 class Data2{ // 數字 資源類 private int number = 0; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); //condition.await(); // 等待 //condition.signalAll(); // 喚醒所有 //+1 public void increment() throws InterruptedException { lock.lock(); try { // 業務代碼 while (number!=0){ //0 // 等待 condition.await(); } number++; System.out.println(Thread.currentThread().getName()+"=>"+number); // 通知其餘線程,我+1完畢了 condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } //-1 public synchronized void decrement() throws InterruptedException { lock.lock(); try { while (number==0){ // 1 // 等待 condition.await(); } number--; System.out.println(Thread.currentThread().getName()+"=>"+number); // 通知其餘線程,我-1完畢了 condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
任何一個新的技術,絕對不是僅僅只是覆蓋了原來的技術,優點和補充!
Condition 精準的通知和喚醒線程
/** * A 執行完調用B,B執行完調用C,C執行完調用A */ public class C { public static void main(String[] args) { Data3 data = new Data3(); new Thread(()->{ for (int i = 0; i <10 ; i++) { data.printA(); } },"A").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { data.printB(); } },"B").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { data.printC(); } },"C").start(); } } class Data3{ // 資源類 Lock private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); private int number = 1; // 1A 2B 3C public void printA(){ lock.lock(); try { // 業務,判斷-> 執行-> 通知 while (number!=1){ // 等待 condition1.await(); } System.out.println(Thread.currentThread().getName()+"=>AAAAAAA"); // 喚醒,喚醒指定的人,B number = 2; condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printB(){ lock.lock(); try { // 業務,判斷-> 執行-> 通知 while (number!=2){ condition2.await(); } System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB"); // 喚醒,喚醒指定的人,c number = 3; condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printC(){ lock.lock(); try { // 業務,判斷-> 執行-> 通知 // 業務,判斷-> 執行-> 通知 while (number!=3){ condition3.await(); } System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB"); // 喚醒,喚醒指定的人,c number = 1; condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
本文參考:狂神說java