(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程⭐学妹已收藏

Posted java厂长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程⭐学妹已收藏相关的知识,希望对你有一定的参考价值。

🔥(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程(一)⭐学妹已收藏

❤️‍ 大家好,我是java厂长,今天带你们体验一把多线程高并发的面试高频!❤️‍

关于作者

  • 作者介绍

🍓 博客主页:作者主页

🍓 简介:JAVA领域优质创作者🥇、一名在校大三学生🎓、在校期间参加各种省赛、国赛,斩获一系列荣誉🏆。

🍓 关注我:关注我学习资料、文档下载统统都有,每日定时更新文章,励志做一名JAVA资深程序猿👨‍💻。

JUC学习

1、什么是JUC


源码+官方文档

JUC是 java util concurrent

面试高频问JUC~!

java.util 是Java的一个工具包

业务:普通的线程代码 Thread

Runnable: 没有返回值、效率相比于Callable 相对较低!

2、线程和进程

进程:一个程序,允许一个java程序会进程里面会出现一个java.exe;数据+代码+pcb

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

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

线程:开了一个进程qq,聊天打字,消息提示(线程负责的)

对于Java而言:Thread、Runable、Callable进行开启线程的。

JAVA真的可以开启线程吗? 开不了的!
原因Java没有权限去开启线程、操作硬件的,这是一个native的一个本地方法,它调用的底层的C++代码。

并发、并行

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

  • CPU 只有一核,模拟出来多条线程,那么我们就可以使用CPU快速交替,来模拟多线程。

并行: 多个人并排行走。

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

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

线程的6个状态

public enum State {
    	//创建
        NEW,

    	//运行
        RUNNABLE,
    
    	//阻塞
        BLOCKED,
    
    	//等待
        WAITING,
    
    	//超时等待
        TIMED_WAITING,

    	//终止
        TERMINATED;
    }

面试题:谈一谈wait和sleep区别?

区别waitsleep
操作的类ObjectThread
锁的释放会释放锁抱着锁睡觉
范围同步代码块中任何地方
异常捕获不需要捕获异常需要捕获异常

3、Lock锁(重点)

synchronized锁问题

package com.zmz.day01;
/**
 * @ProjectName: Juc
 * @Package: com.zmz.day01
 * @ClassName: TicketTest
 * @Author: 张晟睿
 * @Date: 2021/9/5 14:01
 * @Version: 1.0
 */
//资源类 属性 + 方法 oop
class Ticket{
    private int num = 50;
    //卖票方式  synchronized 本质:队列 锁
    public synchronized void sale(){
        if(num > 0){
            System.out.println(Thread.currentThread().getName()+ " 卖出了第"+ num +" 张票,剩余:"+ --num +" 张票");
        }
    }
}


public class TicketTest {
    public static void main(String[] args) {
        //多线陈操作
        //并发:多个线程操作同一个资源ticket
        Ticket ticket = new Ticket();
        //@FunctionalInterface 函数式接口 jdk1.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();
    }
}

Lock接口

公平锁: 公平,必须先来后到~;

非公平锁: 不公平,可以插队;(默认为非公平锁)

使用Lock进行操作

package com.zmz.day01;/**
 * @ProjectName: Juc
 * @Package: com.zmz.day01
 * @ClassName: TicketTest2
 * @Author: 张晟睿
 * @Date: 2021/9/5 16:15
 * @Version: 1.0
 */

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *@ClassName TicketTest2
 *@Description
 *@Author 张晟睿
 *@Date 2021/9/5
 **/

class Ticket2{
    /*
    * 加锁三步
    * 1.实例化lock对象
    * 2.lock加锁
    * 3.unlock解锁
    * */
    Lock l = new ReentrantLock();
    private int num = 50;
    //卖票方式  synchronized 本质:队列 锁
    public  void sale(){
        //加锁
        l.lock();
        try {
            //业务代码
            if(num > 0){
                System.out.println(Thread.currentThread().getName()+ " 卖出了第"+ num +" 张票,剩余:"+ --num +" 张票");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //解锁
            l.unlock();
        }
    }
}


public class TicketTest2 {
    public static void main(String[] args) {
        //多线陈操作
        //并发:多个线程操作同一个资源ticket
        Ticket ticket = new Ticket();
        //@FunctionalInterface 函数式接口 jdk1.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();
    }
}
区别synchronizedlock
名称属于关键字属于对象
状态不可以获取锁的状态可以获取锁的状态
锁的管理自动释放锁需要手动加锁以及释放锁
线程自己抱着锁等待
可重入锁,不可以中断的,非公平的可重入的,可以判断锁,可以自己设置公平锁和非公平锁
代码同步适合少量的代码同步适合大量的代码同步

4、生产者消费者问题

synchronized版

package com.zmz.day01;
/**
 * @ProjectName: Juc
 * @Package: com.zmz.day01
 * @ClassName: TicketTest3
 * @Author: 张晟睿
 * @Date: 2021/9/5 16:35
 * @Version: 1.0
 */

/**
 *@ClassName TicketTest3
 *@Description
 *@Author 张晟睿
 *@Date 2021/9/5
 **/
public class TicketTest3 {
    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();
    }
}


//判断等待  业务  唤醒
class Data{
    private int number = 0;
    //      +1操作
    public synchronized void increment() throws InterruptedException {
        if(number != 0 ){
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
    //      -1操作
    public synchronized void decrement() throws InterruptedException{
        if (number == 0){
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
}

问题存在,A线程B线程,现在如果我有四个线程A B C D!该怎么去解决问题

if判断改为While判断就可以解决虚假唤醒的问题。

package com.zmz.day01;
/**
 * @ProjectName: Juc
 * @Package: com.zmz.day01
 * @ClassName: TicketTest3
 * @Author: 张晟睿
 * @Date: 2021/9/5 16:35
 * @Version: 1.0
 */

/**
 *@ClassName TicketTest3
 *@Description
 *@Author 张晟睿
 *@Date 2021/9/5
 **/
//线程之间的通讯问题:生产者和消费者的问题!  等待唤醒,通知唤醒
//线程交替执行 A   B操作同一个资源
public class TicketTest3 {
    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.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 Data{
    private int number = 0;
    //      +1操作
    public synchronized void increment() throws InterruptedException {
        while(number != 0 ){
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
    //      -1操作
    public synchronized void decrement() throws InterruptedException{
        while (number == 0){
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
}

JUC版本的解决A B C D多线程的问题

package com.zmz.day01;
/**
 * @ProjectName: Juc
 * @Package: com.zmz.day01
 * @ClassName: JucTest1
 * @Author: 张晟睿
 * @Date: 2021/9/5 19:34
 * @Version: 1.0
 */

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *@ClassName JucTest1
 *@Description
 *@Author 张晟睿
 *@Date 2021/9/5
 **/
public class JucTest1 {
    public static void main(String[] args) {
        Data2 data = new Data2();

        new Thread(()->{for(int i=0;i<10;i++) {
            data.increment();
        }
        },"A").start();
        new Thread(()->{for(int i=0;i<10;i++) {
            data.decrement();
        }},"B").start();
        new Thread(()->{for(int i=0;i<10;i++) {
            data.increment();
        }
        },"C").start();
        new Thread(()->{for(int i=0;i<10;i++) {
            data.decrement();
        }
        },"D").start();
    }
}


class Data2{
    private int number = 0;
    //lock锁
    Lock l = new ReentrantLock()以上是关于(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程⭐学妹已收藏的主要内容,如果未能解决你的问题,请参考以下文章

熬夜爆肝万字C#基础入门大总结建议收藏

熬夜爆肝万字C#基础入门大总结建议收藏

建议收藏|熬夜爆肝万字文带你了解DOM,文末有彩蛋嗷!!!!✨✨✨

建议收藏|熬夜爆肝万字文带你了解DOM,文末有彩蛋嗷!!!!✨✨✨

[MySQL]爆肝万字,带你入门MySQL(SQL语句命令大全)

中秋节爆肝万字,带你熟悉Linux进程的基本操作!!!