并发面试合集

1.创建线程的方式

区分线程和线程体的概念,线程体通俗点说就是任务。创建线程体的方式:像实现Runnable、Callable接口、继承Thread类、创建线程池等等,这些方式并没有真正创建出线程,严格来说,Java就只有一种方式可以创建线程,那就是通过new Thread().start()创建。
而所谓的Runnable、Callable……对象,这仅仅只是线程体,也就是提供给线程执行的任务,并不属于真正的Java线程,它们的执行,最终还是需要依赖于new Thread()……

比如我们以new Runnable接口:

我们自定义了一个Runnable接口,通过主线程直接run,接着创建一个新线程并执行对应的任务。
注意:如果在这行的下面让主线程睡一会,再对这个runnable1任务调用run方法,JVM 可能会忽略第二次调用 run() 方法,尤其是在线程已经执行完毕的情况下。
其他的方法都差不多,本质都是只创建了任务(线程体),而不是线程。

线程是执行线程体的容器,线程体是一个可运行的任务

2.如何理解线程安全与不安全

线程安全和不安全是在多线程环境下对于同一份数据的访问是否能够保证其正确性和一致性的描述。

线程安全指的是在多线程环境下,对于同一份数据,不管有多少个线程同时访问,都能保证这份数据的正确性和一致性。

线程不安全则表示在多线程环境下,对于同一份数据,多个线程同时访问时可能会导致数据混乱、错误或者丢失。

//TODO 一些场景下判断是否线程安全,如果不安全,有什么手段让其变的线程安全?

3.(线程)死锁

在多线程编程中,我们为了防止多线程竞争共享资源而导致数据错乱,都会在操作共享资源之前加上互斥锁,只有成功获得到锁的线程,才能操作共享资源,获取不到锁的线程就只能等待,直到锁被释放。

那么,当两个线程为了保护两个不同的共享资源而使用了两个互斥锁,那么这两个互斥锁应用不当的时候,可能会造成两个线程都在等待对方释放锁,在没有外力的作用下,这些线程会一直相互等待,就没办法继续运行,这种情况就是发生了死锁

概括:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止

public class deadLock {
    // 创建两把锁
    static final Object resource1 = new Object();
    static final Object resource2 = new Object();

    public static void main(String[] args) {
        new Thread(()->{
            synchronized(resource1){
                System.out.println(Thread.currentThread().getName()+"持有resource1锁...");
                try {
                    sleep(1000);
                    synchronized(resource2){
                        System.out.println(Thread.currentThread().getName()+"持有resource2锁...");
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally{
                    System.out.println(Thread.currentThread().getName()+"释放锁");
                }
            }
        }).start();
        new Thread(()->{
           synchronized(resource2){
               System.out.println(Thread.currentThread().getName()+"持有resource2锁");
               try {
                   sleep(1000);
                   synchronized(resource1){
                       System.out.println(Thread.currentThread().getName()+"持有resource1锁...");
                   }
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }finally{
                   System.out.println(Thread.currentThread().getName()+"释放锁");
               }
           }
        }).start();
    }
}

如何预防死锁? 资源有序分配法

线程 A 和 线程 B 获取资源(尝试获取锁)的顺序要一样,当线程 A 是先尝试获取资源 A,然后尝试获取资源 B 的时候,线程 B 同样也是先尝试获取资源 A,然后尝试获取资源 B。也就是说,线程 A 和 线程 B 总是以相同的顺序申请自己想要的资源。Future

4.Future接口

用于异步,主要用在一些需要执行耗时任务的场景,避免程序一直原地等待耗时任务执行完成,执行效率太低。具体来说是这样的:当我们执行某一耗时的任务时,可以将这个耗时任务交给一个子线程去异步执行,同时我们可以干点其他事情,不用傻傻等待耗时任务执行完成。等我们的事情干完后,我们再通过 Future类获取到耗时任务的执行结果。这样一来,程序的执行效率就明显提高了。(多路复用?)
我有一个耗时任务,交给Future去做,(期间我可以做其他事,我也可以去查看任务是否完成,是否被取消等等),将来我直接去找Future要任务的执行结果。

// V 代表了Future执行的任务返回值的类型
public interface Future<V> {
    // 取消任务执行
    // 成功取消返回 true,否则返回 false
    boolean cancel(boolean mayInterruptIfRunning);
    // 判断任务是否被取消
    boolean isCancelled();
    // 判断任务是否已经执行完成
    boolean isDone();
    // 获取任务执行结果
    V get() throws InterruptedException, ExecutionException;
    // 指定时间内没有返回计算结果就抛出 TimeOutException 异常
    V get(long timeout, TimeUnit unit)

        throws InterruptedException, ExecutionException, TimeoutExceptio

}

FutureTask(实现)类

同时实现了Future接口和Runnable接口,本身是个Task,因此也是个线程体(任务),可以作为参数放到Thread的构造器里,或者通过线程池的submit方法(返回值是Future)来配合使用
submit和execute的区别? execute方法无返回值

public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        Future<String> submit = executorService.submit(new Callable1());
        System.out.println(submit );//[Not completed]
        String result = submit.get(); // 需要用get方法阻塞拿任务执行结果,
                                     //这个submit只是个future引用,拿他没啥用
        System.out.println(result);  // 获取任务执行结果
        System.out.println(submit );//[Completed normally]
        // 休眠一秒钟,关闭线程池(不然这个线程不会被回收,服务不会关闭)
        sleep(1000);
        executorService.shutdown();
    }

 结论:线程池中的submit方法:对于一个任务,无论是实现Runnable接口、Callable接口还是一个FutureTask,底层都是封装为FutureTask,而FutureTask对象本身是实现Runnable接口的

FutureTask类本身的run方法,就是执行Runnable、Callable的实现类并获取返回结果的过程。

ExecutorService接口中submit方法归根结底还是要把你传入的对象封装成FutureTask对象,并通过FutureTask类的内部实现来获取结果的,无论是直接传入自己的Runnable、Callable实现类还是构建FutureTask对象传入,本质上都是通过FutureTask去实现,没有什么区别;

 CompletableFuture(实现)类

提出场景:Future在实际使用过程中存在一些局限性比如不支持异步任务的编排组合(可以将多个异步任务串联起来,组成一个完整的链式调用)、获取计算结果的 get() 方法为阻塞调用。
提供了函数式编程的能力,可以通过回调的方式处理计算结果

创建异步对象

参数如果没带Executor,则用ForkJoinPool.commonPool() 作为它的线程池执行异步代码

supplyAsync 有返回值 runAsync无返回值

static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

 创建回调

whenComplete可以处理正常和异常的计算结果,exceptionally处理异常情况。
BiConsumer<? super T,? super Throwable>可以定义处理业务

whenComplete 和 whenCompleteAsync 的区别:

前者当前线程继续执行,后者把任务提交给线程池

public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action);
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action);
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor);

public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn);

线程串行化

thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值。

thenAccept方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。

thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun的后续操作

带有Async默认是异步执行的。这里所谓的异步指的是不在当前线程内执行。

public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);

public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);

多任务组合

前者所有任务完成,后者有一个完成即可。

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs);

public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs);

5.原子类

参考: 异步编排(CompletableFuture异步调用)-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/qq_33524158/article/details/107243344

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/884489.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pygame中Sprite实现逃亡游戏4

在《Pygame中Sprite实现逃亡游戏3》中实现了玩家跳跃飞火的效果&#xff0c;接下来通过精灵类的碰撞检测来判断飞火是否击中玩家、飞火是否击中飞龙以及飞龙是否抓住玩家。 1 飞火是否击中玩家的判断 判断飞火是否击中玩家的代码如图1所示。 图1 判断飞火是否击中玩家的代码 …

【07】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-Swiper轮播组件与样式结构重用

序言&#xff1a; 本文详细讲解了关于我们在页面上经常看到的轮播图在鸿蒙开发中如何用Swiper实现&#xff0c;介绍了Swiper的基本用法与属性&#xff0c;及如何面对大段的重复代码进行封装和重用&#xff08;Extend、Styles、Builder&#xff09;&#xff0c;使代码更加简洁易…

Miniforge详细安装教程(macOs和Windows)

(注&#xff1a;主要是解决商业应用anaconda收费问题&#xff0c;这是轻量级的代替&#xff0c;个人完全可以使用anaconda和miniconda) Miniforge 是一个轻量级的包管理器&#xff0c;类似于 Anaconda 和 Miniconda。它主要用于安装基于 conda 的 Python 环境&#xff0c;专注于…

9.26 Buu俩题解

[CISCN2019 华东北赛区]Web2 看wp写完之后写的 知识点 存储型XSS与过滤绕过sql注入 题解 好几个页面&#xff0c;存在登录框可以注册&#xff0c;存在管理员页面(admin.php) ->既然存在管理员页面&#xff0c;且直接访问admin.php提示我们 说明存在身份验证&#xff0…

K8S的Pod IP

pod 的ip 一般是提供给pod1与pod2之间的通信&#xff0c;它有两个特点 1. Pod IP会随着Pod实例 的创新创建&#xff08;重启&#xff09;发生变化&#xff1b; 2. Pod IP只在集群内节点可见&#xff0c;外部无法直接访问

椭圆距离计算的简单方法

分析发现找到点到椭圆的最近距离等价于求解一元四次方程。想象一下一个圆和一个椭圆最多相交四次。从这个观点出发,问题转化为找到与椭圆仅相交一次的圆。如果用四次方程表示,其中两个根将在交点处共享,而另外两个根将会是复数。 尽管四次方程的封闭解确实存在,但迭代方法更…

使用Python和OpenCV生成灰阶图像

代码如下&#xff1a; import cv2 import numpy as npimg np.zeros((256, 256), np.uint8)for i in range(0,16):for j in range(0,16):img[i*16:(i1)*16][j*16:(j1)*16]i*16jcv2.imwrite(result.jpg, img) 效果如下&#xff1a;

Power Automate 设置流Owner不生效的bug

在查找某个功能没生效时&#xff0c;定位到是一个Power automate的流停了&#xff0c;查看原因是因为创建流的owner被disable了 但是当把流的owner更新为可用的用户时&#xff0c;流依旧没被触发&#xff0c;触发的条件很简单&#xff0c;某个表的记录创建时&#xff0c;因为是…

操作系统与进程

1.操作系统 操作系统是计算机中的一个重要软件&#xff0c;它是一个专门进行管理的软件。操作系统可以通过驱动程序来间接管理外部硬件&#xff0c;也可以为计算机中的程序提供一个稳定的运行环境&#xff0c;从而来方便管理各种程序的运行&#xff0c;让程序之间的运行互不影…

传知代码-基于图神经网络的知识追踪方法(论文复现)

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 1.论文概述 论文链接提出了一种基于图神经网络的知识追踪方法&#xff0c;称为基于图的知识追踪&#xff08;GKT&#xff09;。将知识结构构建为图&#xff0c;其中节点对应于概念&#xff0c;边对应于它们之间的…

【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 一&#xff1a;单例模式&#xff08;singleton&#xff09; 1&#xff1a;概念 二&#xff1a;“饿汉模…

Enhancing Trust in LLMs: Algorithms for Comparing and Interpreting LLMs

文章目录 题目摘要引言透明度的必要性对信任的追求困惑度测量自然语言处理(NLP)评估指标零投学习绩效少量学习性能迁移学习对抗测试公平和偏见稳健性评估LLMMaps基准测试和排行榜分层分析布鲁姆分类法的可视化幻觉评分知识分层策略利用机器学习模型进行层级生成注意力可视化LLM…

css五种定位总结

在 CSS 中&#xff0c;定位&#xff08;Positioning&#xff09;主要有五种模式&#xff0c;每种模式的行为和特点不同&#xff0c;以下是 static、relative、absolute、fixed 和 sticky 五种定位方式的对比总结&#xff1a; 1. static&#xff08;默认定位&#xff09; 特性…

阿里云函数计算 x NVIDIA 加速企业 AI 应用落地

作者&#xff1a;付宇轩 前言 阿里云函数计算&#xff08;Function Compute, FC&#xff09;是一种无服务器&#xff08;Serverless&#xff09;计算服务&#xff0c;允许用户在无需管理底层基础设施的情况下&#xff0c;直接运行代码。与传统的计算架构相比&#xff0c;函数…

【2023工业3D异常检测文献】PointCore: 基于局部-全局特征的高效无监督点云异常检测器

PointCore: Efficient Unsupervised Point Cloud Anomaly Detector Using Local-Global Features 1、Background 当前的点云异常检测器可以分为两类&#xff1a; &#xff08;1&#xff09;基于重建的方法&#xff0c;通过自动编码器重建输入点云数据&#xff0c;并通过比较原…

07-阿里云镜像仓库

07-阿里云镜像仓库 注册阿里云 先注册一个阿里云账号&#xff1a;https://www.aliyun.com/ 进入容器镜像服务控制台 工作台》容器》容器服务》容器镜像服务 实例列表》个人实例 仓库管理》镜像仓库》命名空间》创建命名空间 仓库管理》镜像仓库》镜像仓库》创建镜像仓库 使…

【AI】深度学习的数学--核心公式

1 梯度下降 f ( x Δ x , y Δ y ) ≃ f ( x , y ) ∂ f ( x , y ) ∂ x Δ x ∂ f ( x , y ) ∂ y Δ y f(x\Delta x,y\Delta y) \simeq f(x,y)\frac{\partial f(x,y)}{\partial x}\Delta x\frac{\partial f(x,y)}{\partial y}\Delta y f(xΔx,yΔy)≃f(x,y)∂x∂f(x,y)​…

MySQL 性能剖析全攻略

在使用 MySQL 数据库的过程中&#xff0c;性能问题往往是让开发者和管理员头疼的难题。为了有效地解决这些问题&#xff0c;我们需要对 MySQL 进行性能剖析。那么&#xff0c;如何在 MySQL 中进行性能剖析呢&#xff1f;本文将为你详细介绍。 一、为什么要进行性能剖析&#x…

基于安卓开发大型体育场管理系统的设计与实现(源码+定制+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

《开题报告》基于SpringBoot框架的高校专业实习管理系统开题报告的设计与实现源码++学习文档+答辩讲解视频

开题报告 研究背景 在当今高等教育日益普及与深化的背景下&#xff0c;高校专业实习作为学生将理论知识转化为实践能力、提前适应社会工作环境的重要环节&#xff0c;其重要性不言而喻。然而&#xff0c;传统的高校专业实习管理模式往往存在信息不对称、流程繁琐、效率低下、…