JUC学习

JUC学习

1、 Lock锁

  • synchronized
public class SaleTicketDemo01 {
    public static void main(String[] args) {
        //并发,多个线程操作一个资源
        Ticket ticket = new Ticket();
        //函数式接口
        //创建线程,把资源丢进线程中
        //jdk 1.8 lambda表达式   (参数)->{代码}
        new Thread(()->{
            for (int i = 0; i < 60; i++){
                ticket.sale();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 60; i++){
                ticket.sale();
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 60; i++){
                ticket.sale();
            }
        },"C").start();
    }
}
class Ticket{
    private int number = 50;
    //synchronized的本质是 队列 + 锁
    public synchronized void sale(){
        if (number>0) {
            System.out.println(Thread.currentThread().getName()+"卖出了第"+(number--)+"张票,剩余"+number+"张票");
        }
    }
}
  • Lock
public class SaleTicketDemo02 {
    public static void main(String[] args) {
        //并发,多个线程操作一个资源
        Ticket2 ticket = new Ticket2();
        new Thread(() -> { for (int i = 0; i < 60; i++) ticket.sale(); }, "A").start();
        new Thread(() -> { for (int i = 0; i < 60; i++) ticket.sale(); }, "B").start();
        new Thread(() -> { for (int i = 0; i < 60; i++) ticket.sale(); }, "C").start();

    }
}
// lock三部曲
// 1. new ReentrantLock
// 2. lock.lock() //加锁
// 3. finally=> lock.unlock()  //解锁
class Ticket2{
    private int number = 50;

    Lock lock = new ReentrantLock();

    public synchronized 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的区别

  1. synchronized是一个关键字,lock是一个类;
  2. synchronized不能判断锁的状态,lock可以判断锁的状态;
  3. synchronized是一个全自动的锁,不用解锁,lock需要手动解锁,如果不解锁,就会死锁;
  4. synchronized 线程1(获得锁,阻塞),线程2(等待,傻傻的等),lock不一定会等,tryLock

2、生产者消费者问题

生产者消费者synchronized版

// 生产者和消费者问题,即两个线程去操作同一个资源 number
// 生产者 number++
// 消费者 number--
public class ProductConsumer {
    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();
                }
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"B").start();
    }
}
//判断等待 业务 通知 (生产者和消费者三部曲)
class Data{
    private int number = 0;
    public synchronized void increment() throws InterruptedException {
        if (number != 0 ){
            //等待
            this.wait();
        }
        number ++;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
    public synchronized void decrement() throws InterruptedException {
        if (number == 0){
            //等待
            this.wait();
        }
        number --;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
}

存在的问题,上面是两个线程,如果是四个线程呢 ABCD,线程死锁,程序崩溃

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dqeo5eXa-1631506927300)(C:\Users\15067\AppData\Roaming\Typora\typora-user-images\image-20200225134515046.png)]

  • 原因

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FeCsKuQn-1631506927302)(C:\Users\15067\AppData\Roaming\Typora\typora-user-images\image-20200225135508385.png)]

  • 解决:改成while判断

JUC版生产者消费者问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EqM3BKNb-1631506927303)(C:\Users\15067\AppData\Roaming\Typora\typora-user-images\image-20200225140752391.png)]

//Condition + Lock
public class ProAndCsmLock {
    public static void main(String[] args) {
        Data02 data = new Data02();
        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.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } 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 Data02{
    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public void increment() throws InterruptedException {
        try {
            lock.lock();
            while (number != 0 ){
                //等待
                condition.await();
            }
            number ++;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public synchronized void decrement() throws InterruptedException {
        try {
            lock.lock();
            while (number == 0 ){
                //等待
                condition.await();
            }
            number --;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
}

Condition实现精确唤醒锁,具有监视器的功能

// 在多线程下,实现业务A -> 业务B-> 业务C 顺序执行
public class ProAndCsmLock02 {
    public static void main(String[] args) {
        Print print = new Print();
        new Thread(()->{print.printA();},"A").start();
        new Thread(()->{print.printB();},"B").start();
        new Thread(()->{print.printC();},"C").start();
    }
}
//判断等待 业务 通知 (生产者和消费者三部曲)
class Print{
    Lock lock = new ReentrantLock();
    private int number = 1;
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();

    public void printA(){
        try {
            lock.lock();
            while( number !=1 ){
                condition1.await();
            }
            number = 2;
            System.out.println(Thread.currentThread().getName()+"业务A执行");
            condition2.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void printB(){
        try {
            lock.lock();
            while( number != 2){
                condition2.await();
            }
            number = 3;
            System.out.println(Thread.currentThread().getName()+"业务B执行");
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void printC(){
        try {
            lock.lock();
            while(number !=3){
                condition3.await();
            }
            number = 1;
            System.out.println(Thread.currentThread().getName()+"业务C执行");
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
上一篇:juc并发编程学习笔记上(尚硅谷)


下一篇:面试必备系列JUC(6)--八锁详解