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

java厂长 java厂长     2023-01-13     181

关键词:

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

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

关于作者

  • 作者介绍

🍓 博客主页:作者主页

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

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

JUC学习

15、异步回调

Future 设计的初衷:对将来的某个事件结果进行建模!

其实就是前端 —》发送ajax异步请求给后端

但是我们平时都使用CompletableFuture

(1)没有返回值的runAsync异步回调

package com.zmz.Async;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @ProjectName: Juc
 * @Package: com.zmz.Async
 * @ClassName: runAsync
 * @Author: 张晟睿
 * @Date: 2021/10/11 18:58
 * @Version: 1.0
 */
public class runAsync 
    public static void main(String[] args) throws ExecutionException, InterruptedException
    
        // 发起 一个 请求

        System.out.println(System.currentTimeMillis());
        System.out.println("---------------------");
        CompletableFuture<Void> future = CompletableFuture.runAsync(()->
            //发起一个异步任务
            try 
                TimeUnit.SECONDS.sleep(2);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            System.out.println(Thread.currentThread().getName()+".....");
        );
        System.out.println(System.currentTimeMillis());
        System.out.println("------------------------------");
        //输出执行结果
        System.out.println(future.get());  //获取执行结果
    

(2)有返回值的异步回调supplyAsync

package com.zmz.Async;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @ProjectName: Juc
 * @Package: com.zmz.Async
 * @ClassName: supplyAsync
 * @Author: 张晟睿
 * @Date: 2021/10/11 19:09
 * @Version: 1.0
 */
public class supplyAsync 
    public static void main(String[] args) throws ExecutionException, InterruptedException 
        //有返回值的异步回调
        CompletableFuture<Integer> completableFuture=CompletableFuture.supplyAsync(()->
            System.out.println(Thread.currentThread().getName());
            try 
                TimeUnit.SECONDS.sleep(2);
                int i=1/0;
             catch (InterruptedException e) 
                e.printStackTrace();
            
            return 1024;
        );
        System.out.println(completableFuture.whenComplete((t, u) -> 
            /*我们可以看到whenComplete以上的程序有两个参数,一个是t 一个是u
            T:是代表的 正常返回的结果;
            U:是代表的 抛出异常的错误信息;
           如果发生了异常,get可以获取到exceptionally返回的值;
            */
            //success 回调
            System.out.println("t=>" + t); //正常的返回结果
            System.out.println("u=>" + u); //抛出异常的 错误信息
        ).exceptionally((e) -> 
            //error回调
            System.out.println(e.getMessage());
            return 404;
        ).get());
    

16、JMM(Java Memory Model )

1)我们先了解一下什么JMM?

JMM:JAVA内存模型,不存在的东西,抽象的,是一个概念,也是一个约定!

关于JMM的一些同步的约定:

  1. 线程解锁前,必须把共享变量立刻刷回主存
  2. 线程加锁前,必须读取主存中的最新值到工作内存中
  3. 加锁和解锁是同一把锁

线程中分为 工作内存、主内存

八种操作:

名称描述
Read(读取)作用于主内存变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用
load(载入)作用于工作内存的变量,它把read操作从主存中变量放入工作内存中
Use(使用)作用于工作内存中的变量,它把工作内存中的变量传输给执行引擎,每当虚拟机遇到一个需要使用到变量的值,就会使用到这个指令
assign(赋值)作用于工作内存中的变量,它把一个从执行引擎中接受到的值放入工作内存的变量副本中
store(存储)作用于主内存中的变量,它把一个从工作内存中一个变量的值传送到主内存中,以便后续的write使用
write(写入)作用于主内存中的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中
lock(锁定)作用于主内存的变量,把一个变量标识为线程独占状态
unlock(解锁)作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定


对于八种操作给了相应的规定:

  • 不允许read和load、store和write操作之一单独出现。即使用了read必须load,使用了store必须write
  • 不允许线程丢弃他最近的assign操作,即工作变量的数据改变了之后,必须告知主存
  • 不允许一个线程将没有assign的数据从工作内存同步回主内存
  • 一个新的变量必须在主内存中诞生,不允许工作内存直接使用一个未被初始化的变量。就是对变量实施use、store操作之前,必须经过assign和load操作
  • 一个变量同一时间只有一个线程能对其进行lock。多次lock后,必须执行相同次数的unlock才能解锁
  • 如果对一个变量进行lock操作,会清空所有工作内存中此变量的值,在执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值
  • 如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量
  • 对一个变量进行unlock操作之前,必须把此变量同步回主内存

遇到问题程序不知道主存中的值已经被修改过了!

17、volatile

1)保证可见性

package com.zmz.JMM;

import java.util.concurrent.TimeUnit;

/**
 * @ProjectName: Juc
 * @Package: com.zmz.JMM
 * @ClassName: JMMdemo01
 * @Author: 张晟睿
 * @Date: 2021/10/11 20:43
 * @Version: 1.0
 */
public class JMMdemo01 
    // 如果不加volatile 程序会死循环
    // 加了volatile是可以保证可见性的
    private volatile static Integer number = 0;

    public static void main(String[] args) 
        //main线程
        //子线程1
        new Thread(()->
            while (number==0)
            
        ).start();
        try 
            TimeUnit.SECONDS.sleep(2);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        //子线程2
        new Thread(()->
            while (number==0)
            

        ).start();
        try 
            TimeUnit.SECONDS.sleep(2);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        number=1;
        System.out.println(number);
    

2)不保证原子性

原子性:意思就是说不可分割,举一个例子就是说线程A在执行任务的时候,不能被打扰的,也不能被分割的,要么同时成功,要么同时失败。

package com.zmz.JMM;

/**
 * @ProjectName: Juc
 * @Package: com.zmz.JMM
 * @ClassName: JMMdemo02
 * @Author: 张晟睿
 * @Date: 2021/10/11 20:46
 * @Version: 1.0
 */
public class JMMdemo02 
    private static volatile int num = 0;

    public static void add()
        num++;
        //++ 不是一个原子性操作,是2个~3个操作
    

    public static void main(String[] args) 
        //理论上number  === 20000

        for (int i = 1; i <= 20; i++) 
            new Thread(()->
                for (int j = 1; j <= 1000 ; j++) 
                    add();
                
            ).start();
        

        while (Thread.activeCount()>2)
            //main  gc
            Thread.yield();
        
        System.out.println(Thread.currentThread().getName()+",num="+num);
    

使用原子类

package com.zmz.JMM;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ProjectName: Juc
 * @Package: com.zmz.JMM
 * @ClassName: JMMdemo03
 * @Author: 张晟睿
 * @Date: 2021/10/11 21:05
 * @Version: 1.0
 */
public class JMMdemo03 
    private static volatile AtomicInteger number = new AtomicInteger();

    public static void add()
//        number++;
        number.incrementAndGet();  //底层是CAS保证的原子性
    

    public static void main(String[] args) 
        //理论上number  === 20000

        for (int i = 1; i <= 20; i++) 
            new Thread(()->
                for (int j = 1; j <= 1000 ; j++) 
                    add();
                
            ).start();
        

        while (Thread.activeCount()>2)
            //main  gc
            Thread.yield();
        
        System.out.println(Thread.currentThread().getName()+",num="+number);
    

这些类的底层都直接和操作系统挂钩!是在内存中修改值。

3)禁止指令重排

什么是指令重排?

我们写的程序,计算机并不是按照我们自己写的那样去执行的

源代码–>编译器优化重排–>指令并行也可能会重排–>内存系统也会重排–>执行

处理器在进行指令重排的时候,会考虑数据之间的依赖性!

int x=2; //1
int y=4; //2
x=x+10;   //3
y=x*x;   //4

//我们期望的执行顺序是 1_2_3_4  可能执行的顺序会变成3124 1423
//可不可能是 4123? 不可能的
1234567

可能造成的影响结果:前提:a b x y这四个值 默认都是0

线程A线程B
x=ay=b
b=1a=2

正常的结果: x = 0; y =0

线程A线程B
b=1a=2
x=ay=b

可能在线程A中会出现,先执行b=1,然后再执行x=a

在B线程中可能会出现,先执行a=2,然后执行y=b

那么就有可能结果如下:x=4; y=2

volatile可以避免指令重排:

volatile中会加一道内存的屏障,这个内存屏障可以保证在这个屏障中的指令顺序。

内存屏障:CPU指令。作用:保证特定的操作的执行顺序;可以保证某些变量的内存可见性(利用这些特性,就可以保证volatile实现的可见性)

4)总结

  • 由于内存屏障,可以保证避免指令重排的现象产生
  • 不能保证原子性
  • volatile可以保证可见性

🥰面试题:在哪里用这个内存屏障用得最多呢?

单例模式

18、单例模式

1)饿汉式

package single;

//饿汉式单例模式
@SuppressWarnings("all")
public class Hungry 
	
	private byte[] date1= new byte[1024*1024];
	private byte[] date2= new byte[1024*1024];
	private byte[] date3= new byte[1024*1024];
	private byte[] date4= new byte[1024*1024];
	private Hungry()
		
	
	private final static Hungry HUNGRY = new Hungry();
	
	public static Hungry getInstance()
		return HUNGRY;
	


2)DCL懒汉式

package single;

import java.lang.reflect.Constructor;

//懒汉式
public class LazyMan 

	private LazyMan()
		synchronized(LazyMan.class)
			throw new RuntimeException("不要试图使用反射破坏异常");
		
//		System.out.println(Thread.currentThread().getName()+"ok");
	
	
	private static  LazyMan lazyMan;
	//双重检测锁
	public static LazyMan getInstance()
		if (lazyMan==null) 
			synchronized (LazyMan.class) 
				if (lazyMan==null) 
					lazyMan = new LazyMan();
					//不是原子性操作
					//1.分配内存空间
					//2.执行构造方法,初始化对象
					//3.把这个对象指向空间
				
			
			
		
		return lazyMan;
	
	
	public static void main(String[] args) throws Exception 
//		LazyMan instance = LazyMan.getInstance();
		Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
		declaredConstructor.setAccessible(true);
		LazyMan instance = declaredConstructor.newInstance();
		LazyMan instance2 = declaredConstructor.newInstance();
		System.out.println(instance);
		System.out.println(instance2);
				for (int i = 0; i < 2; i++) 
			new Thread(()->
				LazyMan.getInstance();
			).start();
		
	

3)静态内部类

package single;

public class Holder 
	
	private Holder()
	
	private static Holder getInstance()
		return InnerClass.HOLDER;
	
	
	public static class InnerClass 
		private static final Holder HOLDER = new Holder();
	

单例不安全, 主要的原因是因为反射。

4)枚举

package com.zmz.Singleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @ProjectName: Juc
 * @Package: com.zmz.Singleton
 * @ClassName: EnumSingle
 * @Author: 张晟睿
 * @Date: 2021/10/12 20:06
 * @Version: 1.0
 */
//enum 是什么? enum本身就是一个Class 类
public enum EnumSingle 
    INSTANCE;
    public EnumSingle getInstance()
        return INSTANCE;
    


class Test
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException 
        EnumSingle instance1 = EnumSingle.INSTANCE;
        Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
        declaredConstructor.setAccessible(true);
        //java.lang.NoSuchMethodException: com.ogj.single.EnumSingle.<init>()

        EnumSingle instance2 = declaredConstructor.newInstance();
        System.out.println(instance

熬夜爆肝万字c#基础入门大总结建议收藏(代码片段)

往期文章分享点击跳转=>熬夜再战Android从青铜到王者-UI组件快速搭建App界面点击跳转=>熬夜再战Android从青铜到王者-几个适配方案点击跳转=>熬夜再战Android从青铜到王者-开发效率插件篇点击跳转=>Unity粒子特... 查看详情

熬夜爆肝万字c#基础入门大总结建议收藏(代码片段)

...List/立体画廊等,玩出花儿来点击跳转=>Unity新手必备5款宝藏插件–价值上千元白嫖最新版👉关于作者众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多... 查看详情

建议收藏|熬夜爆肝万字文带你了解dom,文末有彩蛋嗷!!!!✨✨✨(代码片段)

感激相遇你好我是阿ken作者:请叫我阿ken链接:请叫我阿ken主页链接来源:CSDN著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。🌊🌈关于前言:文章部分内容及图片出自网... 查看详情

建议收藏|熬夜爆肝万字文带你了解dom,文末有彩蛋嗷!!!!✨✨✨(代码片段)

感激相遇你好我是阿ken作者:请叫我阿ken链接:请叫我阿ken主页链接来源:CSDN著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。🌊🌈关于前言:文章部分内容及图片出自网... 查看详情

中秋节爆肝万字,带你熟悉linux进程的基本操作!!!(代码片段)

今天是中秋节,祝各位小伙伴中秋节快乐,记得吃月饼吖图片来自网络,侵联删Linux进程基本操作1.进程基本概念在Linux中进程信息被保存在task_struct(PCB)2.查看进程的方法pspsaux|greapmyprocls/proc3.创建进程fork():创建一个子进程#i... 查看详情

中秋节爆肝万字,带你熟悉linux进程的基本操作!!!(代码片段)

今天是中秋节,祝各位小伙伴中秋节快乐,记得吃月饼吖图片来自网络,侵联删Linux进程基本操作1.进程基本概念在Linux中进程信息被保存在task_struct(PCB)2.查看进程的方法pspsaux|greapmyprocls/proc3.创建进程fork():创建一个子进程#i... 查看详情

❤️爆肝万字!一文最全总结之spring从入门到入土❤️(建议收藏)(代码片段)

文章目录最新更新前言1.Spring概述1.1介绍2.IoC入门2.1什么是IoC2.2IoC入门案例1(基础案例)2.3IoC入门案例2(依赖注入)2.4IoC入门案例3(面向接口编程)2.5IoC入门案例4(整合JUnit4)3.IoC详解3.1Bean的创建... 查看详情

❤️爆肝万字!一文最全总结之spring从入门到入土❤️(建议收藏)(代码片段)

文章目录前言1.Spring概述1.1介绍2.IoC入门2.1什么是IoC2.2IoC入门案例1(基础案例)2.3IoC入门案例2(依赖注入)2.4IoC入门案例3(面向接口编程)2.5IoC入门案例4(整合JUnit4)3.IoC详解3.1Bean的创建3.2依赖注... 查看详情

❤️爆肝万字整理的综合架构web服务之nginx详解❤️,附建议收藏(代码片段)

文章目录nginx服务配置详细介绍关于作者前言一、nginxweb入门简介1.1什么是nginx1.2常见的网站服务1.3nginx网站服务特点1.4网站页面访问原理二、nginx服务部署安装2.1实验环境2.2YUM安装2.3源码编译安装2.4nginx重要文件目录结构2.5虚拟主... 查看详情

万字讲解如何设计百万人抽奖系统?——高并发面试模板,已拿美团offer❤️建议收藏(代码片段)

❤️一条独家专栏⭐️搞技术,进大厂,聊人生📚《大厂面试突击》——面试10多家中大厂的万字总结📚《技术专家修炼》——高薪必备,企业真实场景📚《leetcode300题》——每天一道算法题,进大厂... 查看详情

pythonopencv实战画图——这次一定能行!爆肝万字,建议点赞收藏~❤️❤️❤️(代码片段)

📢📢📢📣📣📣🌻🌻🌻Hello,大家好我叫是Dream呀,一个有趣的Python博主,小白一枚,多多关照😜😜😜🏅🏅 查看详情

☀️~算法系列之爆肝万字总结七种查找算法,持续补充更新中,建议收藏~☀️(代码片段)

🍅作者主页:Roninaxious🍅欢迎点赞👍收藏⭐留言📝🍅话不多说🍁开卷!🚢顺序查找算法🚢二分查找算法💥优化二分查找算法🚢插值查找算法🚢斐波那契查找算法🚢顺序... 查看详情

熬夜爆肝!c++核心进阶知识点汇总整理万字干货预警建议收藏(代码片段)

...C++基础入门知识点,没看过的可以看看喔!熬夜爆肝!C++基础入门大合集【万字干货预警建议收藏】今天继续整 查看详情

❤️大学三年沉淀,把我的学习经验分享给你,爆肝万字带你走进编程世界!❤️(代码片段)

Hello,大家好,我是Alex。时光匆匆,暑假过的很快,转眼又到了大学的开学季,我也是又混进了我们学院的新生群,发现大家对计算机充满着迷之向往,啊哈哈哈,不过没有人带着入门还是很容易... 查看详情

网易一面:如何设计线程池?请手写一个简单线程池?(代码片段)

...a面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪酬猛涨!加尼恩免费领免费赠送经典图书:《Java高并发核心编程(卷1... 查看详情

❤爆肝万字手把手教你springboot+mybatis+jquery+html5从0开始写网页一学就会!(内附源码)❤(代码片段)

今天带给大家的是SpringBoot+MyBatis+jQuery+HTML5+CSS简单实现前后端交互,保证干货满满,看完你就可以动手写你自己的程序!首先得需要你创建一个SpringBoot项目,具体怎么创建这里久不多说啦。其次,... 查看详情

juc高并发编程(代码片段)

文章目录1.什么是JUC1.1.JUC简介1.2.进程与线程1.3.线程的状态1.3.1线程状态枚举类1.3.2.wait/sleep的区别1.4.并发与并行1.4.1.串行模式1.4.2.并行模式1.4.3.并发1.4.4.小结(重点)1.5.管程1.6.用户线程和守护线程2.Lock接口2.1.Synchronized2.1.1.Synchroniz... 查看详情

juc高并发编程(代码片段)

文章目录1.什么是JUC1.1.JUC简介1.2.进程与线程1.3.线程的状态1.3.1线程状态枚举类1.3.2.wait/sleep的区别1.4.并发与并行1.4.1.串行模式1.4.2.并行模式1.4.3.并发1.4.4.小结(重点)1.5.管程1.6.用户线程和守护线程2.Lock接口2.1.Synchronized2.1.1.Synchroniz... 查看详情