多线程进阶——JUC并发编程以前夜

一、什么是JUC

学习能够参考:源码+官方文档 进行学习java

文档地址:https://docs.oracle.com/javase/8/docs/api/面试

首先咱们看看什么是JUC算法

其次咱们看看JUC都有哪些东西编程

因而咱们能够总结下JUC能够分为五大类api

一、同步工具类多线程

二、lock类并发

三、原子类oracle

四、集合相关类框架

五、Executor框架相关类ide

二、JUC入门前言——唠嗑 线程和进程

线程、进程,若是不能使用一句话说出来,说明技术不扎实!

进程:一个程序,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能够在任何地方睡

三、Lock锁(重点)

传统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

https://www.bilibili.com/video/av90007319

相关文章
相关标签/搜索