JUC并发编程《Java-2021面试谈资系列》

本文深入探讨Java并发编程,讲解JUC(java.util.concurrent)包中的重要概念,包括线程和进程的区别、Lock锁的类型与应用、生产者消费者问题、并发集合、线程同步工具如CountDownLatch、CyclicBarrier和Semaphore,以及Volatile的特性和作用。通过对各种锁的比较,展示了在并发场景下如何选择合适的同步机制,并介绍了防止死锁和提高并发性能的策略。
摘要由CSDN通过智能技术生成

一、什么是JUC

JUC简称java.util.concurrent
在这里插入图片描述
面试高频问!!!
业务:普通的线程代码 Thread
Runable:没有返回值,效率相比Callable低

二、线程和进程

线程,进程,一句话表述

进程: 一个程序,QQ.exe 程序的集合;

一个进程可以包含多个线程,至少包含一个!!!

Java默认有几个线程?2个 main,GC

线程: 开了一个进程Typora,写字,自动保存(线程负责的)

Thread、Runnable、Callable

java真的可以开启线程嘛?

开不了,只能通过本地方法去调用,底层的C++去实现
在这里插入图片描述

并发、并行

并发编程:并发、并行

并发:多线程操作同一个资源

  • Cpu 一核,模拟多条线程,快速交替

并行:多个人一起行走

  • Cpu多核,多个线程可以同时执行
public class Test01 {
   
    public static void main(String[] args) {
   
        //获取cpu核数
        System.out.println(Runtime.getRuntime().availableProcessors());
    }
}

并发编程的本质: 充分利用CPU的资源

线程有几个状态

public enum State {
   
        NEW, //新生

        RUNNABLE, //运行

        BLOCKED, //阻塞

        WAITING, //等待

        TIMED_WAITING, //超时等待

        TERMINATED; //终止
    }

wait / sleep区别

1.来自不同的类

wait----Object

sleep----Thread

2.关于锁的释放

wait会释放锁,sleep不会释放锁!

3.使用的范围

wait必须在同步代码块中

sleep可以在任何地方睡

三、Lock锁(重点)

传统的Synchronized

package com.wdit.demo;

/**
 * 买票案例
 * 线程就是一个资源类,没有任何附属的操作
 */
public class SaleTicketDemo01 {
   
    public static void main(String[] args) {
   
        //并发:多线程操作同一个资源类
        Ticket ticket = new Ticket();

        //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();
        }
        },"A").start();
    }
}
class Ticket{
   
    //属性
    private int nums = 30;
    //方法
    public synchronized void sale(){
   
        if(nums>0){
   
            System.out.println(Thread.currentThread().getName()+"卖出了第"+(nums--)+"张票"+",剩余:"+nums);
        }
    }
}

Lock接口
在这里插入图片描述
Lock的实现类ReentrantLock

  • 公平锁
  • 非公平锁
public class SaleTickDemo02 {
   
    public static void main(String[] args) {
   
        //并发:多线程操作同一个资源类
        Ticket2 ticket = new Ticket2();

        //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
class Ticket2{
   
    //属性
    private int nums = 30;

    Lock lock = new ReentrantLock();

    public synchronized void sale(){
   
        lock.lock();//加锁

        try {
   
            //业务代码
            if(nums>0){
   
                System.out.println(Thread.currentThread().getName()+"卖出了第"+(nums--)+"张票"+",剩余:"+nums);
            }
        } catch (Exception e) {
   
            e.printStackTrace();
        }finally {
   
            lock.unlock();//解锁
        }
    }
}
区别:
  • synchronized 内置的Java关键字,Lock是一个java类

  • synchronized无法判断获取锁的状态,Lock可以判断是否获取了锁

  • synchronized会自动释放锁,lock必须要手动释放锁,不释放导致死锁

  • synchronized线程1(获得锁,阻塞)、线程2(一直等待);然而Lock锁不一定会等(lock.trylock尝试获取锁)

  • synchronized可重入锁,不可以中断的,非公平;Lock可重入锁,可以判断锁,非公平(可以自己设置)

  • synchronized适合锁少量的代码同步问题;Lock适合大量的代码同步问题

锁是什么?

四、生产者消费者

Synchronized 版本

/**
 * 线程见的通信问题:生产消费者模型    等待,通知
 * 线程交替执行! A   B 操作同一个变量
 * A ==》+1
 * B ==》-1
 */
public class Producer {
   
    public static void main(String[] args) {
   
        Data data = new Data();
        new Thread(()->{
   
            try {
   
                for (int i=0;i<10;i++) data.increment();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        },"A").start();

        new Thread(()->{
   
            try {
   
                for (int i=0;i<10;i++) data.decrement();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        },"B").start();
    }
}
class Data{
   
    private int num = 0;

    //+1
    public synchronized void increment() throws InterruptedException {
   
        if(num!=0) this.wait(); //等待
        num++; // 业务
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        this.notifyAll(); //通知
    }

    //-1
    public synchronized void decrement() throws InterruptedException {
   
        if(num==0) this.wait(); //等待
        num--; //业务
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        this.notifyAll(); //通知
    }
}

问题,A B C D 4个线程——虚假唤醒
在这里插入图片描述

if修改成While

JUC版本的生产者消费者

通过Lock可以找到Condition

代码实现:

public class Test02 {
   
    public static void main(String[] args) {
   
        Data02 data = new Data02();
        new Thread(()->{
   
            try {
   
                for (int i=0;i<10;i++) data.increment();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        },"A").start();

        new Thread(()->{
   
            try {
   
                for (int i=0;i<10;i++) data.decrement();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        },"B").start();

        new Thread(()->{
   
            try {
   
                for (int i=0;i<10;i++) data.increment();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        },"C").start();

        new Thread(()->{
   
            try {
   
                for (int i=0;i<10;i++) data.decrement();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        },"D").start();
    }
}
class Data02{
   
    private int num = 0;

    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    //+1
    public void increment() throws InterruptedException {
   
        lock.lock();

        try {
   
            while (num!=0) condition.await();//等待
            num++; // 业务
            System.out.println(Thread.currentThread().getName()+"=>"+num);
            condition.signalAll();//唤醒
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        } finally {
   
            lock.unlock();
        }

    }

    //-1
    public void decrement() throws InterruptedException {
   
        lock.lock();

        try {
   
            while (num==0) condition.await();
            num--; //业务
            System.out.println(Thread.currentThread().getName()+"=>"+num);
            condition.signalAll();
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        } finally {
   
            lock.unlock();
        }
    }
}

Condition
在这里插入图片描述

任何一个新的技术绝对不是仅仅覆盖了原来的技术

Condition 精准的通知线程

public class Test03 {
   
    public static void main(String[] args) {
   
        Data03 data = new Data03();
        new Thread(()->{
    for (int i
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值