1504 - Java多线程面试题

少年,思无邪,最最动人。

1.Java中有哪几种创建线程的方式

1.1 继承Thread类

代码示例

class HelloWorld01 extends Thread{
    @Override
    public void run() {
        System.out.println("这是继承 Thread 类方式实现多线程!");
    }
}

public class CreateThread01 {
    public static void main(String[] args) {
        new HelloWorld01().start();
        System.out.println("这是主线程的业务逻辑!");
    }
}

运行结果

这是主线程的业务逻辑!
这是继承 Thread 类方式实现多线程!

缺点:类是单继承的。

1.2 实现Runnable接口

代码示例

class HelloWorld02 implements Runnable{
    @Override
    public void run() {
        System.out.println("这是实现 Runnable 接口方式实现多线程!");
    }
}

public class CreateThread02 {
    public static void main(String[] args) {
        new Thread(new HelloWorld02()).start();
        System.out.println("这是主线程的业务逻辑!");
    }
}

运行结果

这是主线程的业务逻辑!
这是实现 Runnable 接口方式实现多线程!

优缺点:解决单继承问题,但是没有回调。

1.3 实现Callable接口

代码示例

class HelloWorld03 implements Callable {
    @Override
    public Object call() throws Exception {
        return "这是实现 Runnable 接口方式实现多线程!";
    }
}


public class CreateThread03 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask = new FutureTask<>(new HelloWorld03());
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
        System.out.println("这是主线程的业务逻辑!");
    }
}

运行结果

这是实现 Runnable 接口方式实现多线程!
这是主线程的业务逻辑!

1.4 创建线程池

代码示例

class HelloWorld04 extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

public class CreateThread04 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            executorService.execute(new HelloWorld04());
        }
        executorService.shutdownNow();
    }
}

 运行结果

pool-1-thread-1
pool-1-thread-3
pool-1-thread-4
pool-1-thread-5
pool-1-thread-2

2.为什么不建议使用Executors来创建线程池

查看 JDK 源码

可以看到,创建的队列为 LinkedBlockingQueue ,这是一个无界的阻塞队列。使用该线程池执行任务,如果任务过多就会不断地添加到这个队列中,任务越多占用的内存就越多,最终可能耗尽内存,导致OOM。

除此之外,使用这种方式创建线程池不能自定义线程的名字,不利于排查问题。

3.线程池有哪几种状态?每种状态分别表示什么

3.1 RUNNING

Accept new tasks and process queued tasks

表示线程池正常运行,既能接受新的任务,也会正常处理队列中的任务。一切正常状态。

3.2 SHUTDOWN

Don't accept new tasks, but process queued tasks

当调用线程池的 shutdown()方法时,线程池就进入 SHUTDOWN 状态,表示线程池处于正在关闭状态,此状态下线程池不会接受新任务,但是会继续把队列中的任务处理完。

3.3 STOP

Don't accept new tasks, don't process queued tasks, and interrupt in-process tasks 

当调用线程池的 shutdownnow()方法时,线程池马上停止,此状态下线程池既不会接受新任务了,也不会处理队列中的任务,并且正在运行的线程也会被中断

3.4 TIDYING

All tasks have terminated, workerCount is zero, the thread transitioning to state TIDYING will run the terminated() hook method

线程池中没有线程在运行后,线程池的状态。

3.5 TERMINATED 

当调用线程池的 terminated()方法时,线程池的状态。

4.Sychronized 和 ReentrantLock 有哪些不同点

SychronizedReentrantLock
Java中的一个关键字JDK提供的一个类
自动加锁与释放锁需要手动加锁与释放锁
JVM层面的锁API层面的锁
非公平锁公平锁或非公平锁
锁的是对象,锁信息保存在对象头中int类型的state标识来标识锁的状态
底层有锁升级的过程没有锁升级的过程

5.ThreadLocal有哪些应用场景,它的底层是如何实现的

ThreadLocal是Java中提供的线程本地缓存机制,可以利用该机制将数据缓存在某个线程内部,该线程可以在任意时刻、任意方法中获取缓存的数据。

ThreadLocal底层是通过ThreadLocalMap来实现的,每个Thread对象(注意不是ThreadLocal对象)中都存在一个ThreadLocalMap,Map的key为ThreadLocal对象,Map的value为需要缓存的值。

代码示例

public class ThreadLocalDemo {
    // 定义一个ThreadLocal,底层是Map实现
    private static ThreadLocal<String> local = new ThreadLocal<>();

    public static void a() {
        local.set("路明非");
    }

    public static void b() {
        String s = local.get();
        System.out.println(s);
        // 使用完了之后,移除,防止内存泄漏
        local.remove();
    }

    public static void main(String[] args) {
        a();
        b();
    }
}

注意:如果在线程池中使用ThreadLocal会造成内存泄漏,因为当 ThreadLocal 对象使用完之后,应该要把设置的key,value也就是Entry对象进行回收,但线程池中的线程不会回收,而线程对象是通过强引用指向ThreadLocalMap,ThreadLocalMap也是通过强引用指向Entry对象,线程不被回收,Entry对象也就不会被回收,从而出现内存泄漏,解决方法是,手动调用remove方法,手动清除Entry对象。

ThreadLocal经典的应用场景就是连接管理。

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

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

相关文章

Redis 高可用 sentinel

简介 Sentinel提供了一种高可用方案来抵抗节点故障&#xff0c;当故障发生时Redis集群可以自动进行主从切换&#xff0c;程序可以不用重启。 Redis Sentinel集群可以看成是一个Zookeeper集群&#xff0c;他是Redis集群高可用的心脏&#xff0c;一般由3-5个节点组成&#xff0…

从“产品的RFM分析”看如何探索“职业方向”

我们在做产品分析时&#xff0c;经常会用到一种方法“产品的RFM分析”&#xff0c;它是一种客户细分和价值评估的常用方法&#xff0c;广泛应用于电子商务、零售和其他众多行业&#xff0c;它可以帮助企业和产品团队更好地理解用户行为&#xff0c;优化营销策略&#xff0c;提升…

python发邮件给多人的注意事项?如何群发?

python发邮件给多人的效率如何&#xff1f;python发邮件的方法&#xff1f; 在利用Python编程语言实现邮件群发功能时&#xff0c;需要注意许多细节&#xff0c;以确保邮件能有效送达且用户体验良好。AokSend将详细探讨python发邮件给多人时需要注意的各个方面&#xff0c;以帮…

2024年历史、文学与人文艺术国际会议(ICHLH 2024)

2024年历史、文学与人文艺术国际会议&#xff08;ICHLH 2024&#xff09; 2024 International Conference on History, Literature, and Humanities 【重要信息】 大会地点&#xff1a;兰州 大会官网&#xff1a;http://www.ichlh.com 投稿邮箱&#xff1a;ichlhsub-conf.com 【…

【第10章】Vue之Element Plus常用组件

文章目录 前言一、表格1. 带斑马纹表格2. 展示 二、分页1.国际化(中文)2.分页代码3. 展示 三、表单1. 表单代码2. 展示 四、卡片1. 卡片代码2. 展示 总结 前言 通过上一章的快速入门&#xff0c;我们已经学习了按钮使用&#xff0c;接下来学习Element Plus的常用组件&#xff…

02-QWebEngineView的使用

Qt WebEngine_hitzsf的博客-CSDN博客 一、QWebEngineView QWebEngineView 类是一个实现Web浏览器的便捷类&#xff0c;提供了back() 、forward()、reload()、stop() 等方法&#xff0c;可轻松实现页面的前进、后退、重载等导航功能&#xff0c;要实现一个简单的只有网页加载网…

手机网站制作软件是哪些

手机网站制作软件是一种用于设计、开发和创建适用于移动设备的网站的软件工具。随着移动互联网时代的到来&#xff0c;越来越多的用户开始使用手机浏览网页和进行在线交流&#xff0c;因此&#xff0c;手机网站制作软件也逐渐成为了市场上的热门工具。 1. Adobe Dreamweaver&am…

前端某个页面乱码

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; springbootlayui&#xff0c;前后端一体 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 某个页面访问中文乱码&#xff1a; 就是这种。 不是数据库的中文&#xff0c;而是html页…

docker回顾--docker compose详细解释,安装,与常用命令

文章目录 Docker compose简介什么是Docker compose核心概念优势 安装常用命令总结 Docker compose简介 什么是Docker compose Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。它使得开发者可以使用一个单独的 YAML 文件来定义应用所需的所有服务、网络和卷&a…

智慧之选:Vatee万腾平台,引领未来的创新引擎

在数字化浪潮席卷全球的今天&#xff0c;我们身处一个信息爆炸、技术革新的时代。在这样的大背景下&#xff0c;选择一个能够引领我们走向未来的平台显得尤为重要。而Vatee万腾平台&#xff0c;正是这样一个不容错过的智慧之选。 Vatee万腾平台&#xff0c;作为一个集创新、科技…

uni app 树状结构数据展示

树状数据展示&#xff0c;可以点击item 将点击数据给父组件 &#xff0c;满足自己需求。不喜勿喷&#xff0c;很简单可以根据自己需求改哈&#xff0c;不要问&#xff0c;点赞收藏就好 <template><view><view v-for"(node, index) in treeData" :ke…

汇凯金业:现货黄金锁单及解锁策略详解

在现货黄金交易中&#xff0c;锁单是一种常见的操作手法&#xff0c;目的是在市场波动中保护已有盈利或避免亏损扩大。锁单分为锁损单和锁盈单&#xff0c;虽然锁单可以暂时控制风险&#xff0c;但解单操作不当可能会导致更大的损失。本文将详细介绍现货黄金锁单的概念、锁单的…

深入探索Stable Diffusion:从原理到应用的全面解析

目录 一 Stable Diffusion的基本概念 什么是Stable Diffusion? Stable Diffusion与传统生成模型的区别 二 Stable Diffusion的理论基础 扩散过程的数学描述 马尔可夫链蒙特卡罗方法(MCMC) 三 Stable Diffusion的算法实现 基本步骤 代码实现 四 Stable Diffusion的…

springboot优雅shutdown时如何保障异步线程的安全

我前面写了一篇springboot优雅shutdown的文章&#xff0c;看起来一切很美好。 https://blog.csdn.net/chenshm/article/details/139640775 那是因为没有进行多线程测试。如果一个请求中包括阻塞线程&#xff08;主线程&#xff09;和非阻塞线程&#xff08;异步线程&#xff09…

抖音短剧看剧系统是怎么做的?怎么样搭建上线运营?

前言&#xff1a; 当前热门短剧已深入大家的日常&#xff0c;针对一些好的短剧更是吸金无数。今天给大家介绍一下短剧这个项目整个运作模式。 一、一部短剧是怎么样呈现到观众眼前的&#xff1f; 首先影视作品公司拍摄剪辑好短剧 &#xff0c;弄好一切审核后&#xff0c;放到…

[C#] opencvsharp对Mat数据进行序列化或者反序列化以及格式化输出

【简要介绍】 在OpenCVSharp中&#xff0c;FileStorage类用于将数据&#xff08;包括OpenCV的Mat类型数据&#xff09;序列化为XML或YAML格式的文件&#xff0c;以及从这些文件中反序列化数据。以下是关于FileStorage类用法的详细说明&#xff1a; 写入数据&#xff08;序列化…

【分布预测】DistPred:回归与预测的无分布概率推理方法

论文题目&#xff1a;DistPred: A Distribution-Free Probabilistic Inference Method for Regression and Forecasting 论文作者&#xff1a;Daojun Liang, Haixia Zhang&#xff0c;Dongfeng Yuan 论文地址&#xff1a;https://arxiv.org/abs/2406.11397 代码地址&#xff1a…

Mellanoxnvidia ib高速网络常用命令总结

1.spci&#xff1a;检查本地的pci设备。示例&#xff1a;lspci| grep -i mell 2.ofed_info&#xff1a;检测ofed驱动版本。示例&#xff1a;ofed_info-s 3.ibstat&#xff1a;查看本机的ib网卡状态。 4.mst&#xff1a;mellnoax软件管理工具。用来生成IB设备描述符。提供给其他…

Python3发送邮件如何添加附件?怎么配置?

Python3发送邮件的注意事项&#xff1f;如何配置Python3发邮件&#xff1f; Python3发送邮件时添加附件是一项常见的需求。无论是发送报告、图片&#xff0c;还是其他文件&#xff0c;掌握如何在邮件中添加附件至关重要。AokSend将详细介绍Python3发送邮件时如何添加附件&…

一文读懂Java线程状态转换

Java线程有哪些状态?状态如何转换? 线程可以拥有自己的操作栈、程序计数器、局部变量表等资源,它与同一进程内的其他线程共享该进程的所有资源。Java的线程有自己的生命周期,在 Java 中线程的生命周期中一共有 6 种状态。 NewRunnableBlockedWaitingTimed WaitingTerminat…