学习能够参考:源码+官方文档 进行学习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