【面试题】—— Java多线程篇(17题)

news2024/11/24 14:55:04

文章目录

    • 1.什么是多线程?
    • 2.线程和进程的区别?
    • 3.我们为什么要使用线程?线程的优缺点?
    • 4.创建线程的方法有哪些?
    • 5.线程的状态有哪些?
    • 6.线程的优先级?
    • 7.线程常用的方法以及其作用?
    • 8.使用过线程池吗?为什么要使用线程池?
    • 9.Java线程分类?
    • 10.什么是死锁?
    • 11.死锁产生的原因、条件是什么?
    • 12.如何预防死锁?
    • 13.为什么不建议使用Executor静态工程来创建线程池?
    • 14.如何创建线程池?
    • 15.线程池常用的参数有哪些?
    • 16.常用的线程池有哪些?
    • 17.说一下ThreadPoolExecutor线程池的执行流程是什么样的?

1.什么是多线程?

线程是操作系统能够进行运算调度的最小单位。线程是一个程序内部的顺序控制流。

2.线程和进程的区别?

进程包含线程。一个进程中可以存在很多线程,每条线程执行不同的任务。比如你打开网易云一边听歌一遍下载歌曲,那么此时网易云整个应用算是一个进程,而播放音乐是该进程下的一个线程,下载歌曲是该进程下的另一个线程。
线程是比进程更小的执行单元。

3.我们为什么要使用线程?线程的优缺点?

  • 优点
    • 使程序执行效率更高。能够让任务实现并行执行。
    • 更充分的利用CPU资源。更好地利用系统资源。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,大大提高程序的效率。
    • 增加了程序应用性和灵活性。由于同一进程的所有线程是共享同一内存,所以不需要特殊的数据传送机制,不需要建立共享存储区或共享文件,从而使得不同任务之间的协调操作与运行、数据的交互、资源的分配等问题更加易于解决。
    • 提升用户体验。比如那些比较耗时的任务,可以起一个单独线程放到后台进行执行,而用户可以做其他的事情。
  • 缺点
    • 多线程消耗的内存空间比较多。
    • 线程的切换需要消耗资源。
    • 多线程下容易造成死锁和数据不安全的情况。

4.创建线程的方法有哪些?

  • 继承Thread重写run方法。
    • 特点:(1)无法获取子线程返回值。(2)run方法不可以抛出异常。
class MyThread extends Thread {
	@Override
    public void run() {
        // 线程执行的代码
    }
}

// 创建并启动线程
MyThread thread = new MyThread();
thread.start();

  • 实现Runnable接口。
    • 特点:(1)无法获取子线程返回值。(2)run方法不可以抛出异常。
class MyRunnable implements Runnable {
    public void run() {
        // 线程执行的代码
    }
}

// 创建并启动线程
Thread thread = new Thread(new MyRunnable());
thread.start();
  • 实现Callable接口。
    • 特点:(1)可以获取子线程返回值。(2)run方法可以抛异常。

5.线程的状态有哪些?

  • 新生状态(NEW):执行new Thread()时创建线程,线程对象一旦被创建就会处于新生状态。
  • 运行状态(RUNNABLE):执行Start()后,线程处于就绪状态,但是不会立即执行,抢占CUP时间片。
  • 阻塞状态(BLOCKED):在等待monitor(监视器)锁的线程的状态。假如在同一个JVM中,有A、B两个线程并行执行,A首先进入了同步块或者是方法后,线程B此时就处于阻塞状态。
  • 等待状态(WAITING):
  • 限时等待(TIMED_WAITING):
  • 终止状态(TERMINATED/'tɜːrmə,net/):
    在这里插入图片描述

6.线程的优先级?

线程的优先级一共被分为10个等级,线程默认的优先级是5。

  • 在有时间片轮询机制中,“高优先级”的线程的被CUP分配时间片的概率要大于“低优先级”的线程。但是并不是“高优先级”的线程一定会先执行。
  • 在无时间片轮询机制中,“高优先级”的线程会被先执行。如果有“低优先级”的线程正在运行,有“高优先级”的线程处于可运行状态的话,就执行完“低优先 级”的线程后,再执行”高优先级“的线程
class ThreadTest extends Thread{
    public void run(){
        ...
    }
}
...
 Thread t1=new ThreadTest("thread1");    // t1线程
 Thread t2=new ThreadTest("thread2");    // t2线程
 t1.setPriority(1);  // 设置t1的优先级为1
t2.setPriority(5);  // 设置t2的优先级为5

7.线程常用的方法以及其作用?

  • threadTest.run():线程的执行体,一般要重写,执行体中的内容就是当前线程执行的内容。
  • threadTest.start():启动线程的方法,调用此方法那么该线程就处于了就绪状态。
  • Object.wait():使当前线程处于等待(阻塞)状态,并且释放所持有的对象的锁。在使用线程的此方法时,需要处理Interrupted(中断异常)异常。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
    • 调用该方法后当前线程进入睡眠状态,直到以下事件发生。
    • 其他线程调用了该对象的notify方法。
    • 其他线程调用了该对象的notifyAll方法。
    • 其他线程调用了interrupt中断该线程。
    • 时间间隔到了。
  • threadTest.suspend():将线程挂起,必须由其他线程调用resume()。
  • Thread.join():join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的join()方法,直到线程A执行完毕后才会执行线程B。join的主要作用就是:让主线程等待子线程结束才能继续运行。join的底层是调用wait()方法,wait()方法在调用后释放锁资源,所以join方法在调用的时候也是释放锁资源的。使用join()方法也是需要处理Interrupted(中断异常)异常。
  • Thread.yield():暂停当前正在运行的线程对象放弃当前CPU资源,并执行其他线程。让当前处于正在运行的线程回到可运行状态,并允许与当前线程有同样优先级的其它线程获取运行的机会,故yield()的另一个作用是,让具有相同优先级或者高于当前优先级的线程轮替执行。但是调用了yield()方法后,并不能一定让步,因为让步的线程还有可能被其它线程调度程序再次选中,所以可能达不到让步的效果。
  • Thread.sleep():sleep()是一个静态本地方法。让线程睡眠,此期间线程不消耗CPU资源。此方法和wait()方法很像,但是唯一点不同的是:wait()会释放锁资源,而sleep()不会。
  • object.nodify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
  • object.nodifyAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;
  • threadTest.setPriority():设置线程的优先级。
  • Thread.currentThread():输出当前线程。

8.使用过线程池吗?为什么要使用线程池?

我们可以通过ThreadPoolExecutor来创建一个线程池。

如果需要处理大量任务,频繁地创建和销毁线程会浪费时间和效率,尤其是浪费内存。为了让线程重复利用,让它们继续执行其他任务而不是立即销毁,线程池应运而生。

虽然线程池是构建多线程应用程序的强大机制,但使用它并不是没有风险的。与其它多线程应用程序一样,用线程池构建的应用程序容易遭受同步错误和死锁等并发风险。此外,线程池还容易遭受特定的风险,如与池有关的死锁、资源不足和线程泄漏。

9.Java线程分类?

  • 用户线程(User Thread)
    创建的普通线程都是用户线程。
  • 守护线程(Daemon Thread)
    所谓守护线程就是在程序运行的时候在后台提供一种通用服务对线程,比如垃圾回收就是一个守护线程。当所有非守护线程结束后,程序也就终止了,同时会杀死程序中的所有守护线程。
  • 用户线程切换为守护线程
    将用户线程切换为守护线程使用的是Thread.setDaemon()方法。但是要注意切换的时机,必须在该线程启动之间进行设置。否则会报出IllegalThreadStateException()异常,因为不能把运行中的线程转变为守护线程。
  • 用户线程和守护线程的区别
    二者主要的区别就是JVM虚拟机离开的时间。
    用户线程:当存在任何一个用户线程未离开,JVM是不会离开的。
    守护线程:如果只剩下守护线程未离开,JVM是可以离开的。

10.什么是死锁?

两个或者多个进程、线程 无限期地等待永远不会发生的条件,系统处于停滞状态,这就是死锁。

11.死锁产生的原因、条件是什么?

  • 原因:
    • 系统资源不足
    • 进程运行推进的顺序不合适
    • 资源分配不当
  • 条件:
    • 互斥条件:一个资源一次只能被一个线程使用。
    • 占有且等待:一个进程获取了一份资源A,再请求另一个份资源B而阻塞时,对已获得的A资源保持不放。
    • 不可强行占有:进程已获得的资源,在未使用完之前,不能强行剥夺。
    • 循环等待条件:若干线程之间形成一种头尾衔接的循环等待资源关系。

12.如何预防死锁?

通过设置某些限制条件,去破坏死锁的四个条件中的一个或者多个条件,来预防死锁。但是由于所施加的限制条件往往太苛刻,因而导致系统资源利用率和系统吞吐量降低。

  • 打破互斥条件:在系统里取消互斥。若资源不被一个进程独占使用,那么死锁是肯定不会发生的。但一般来说在所列的四个条件中,“互斥”条件是无法破坏的。因此,在死锁预防里主要是破坏其他几个必要条件,而不去涉及破坏“互斥”条件。
  • 打破占有且等待条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待。
    每个进程提出新的资源申请前,必须先释放它先前所占有的资源。
  • 打破不可剥夺条件:当进程占有某些资源后又进一步申请其他资源而无法满足,则该进程必须释放它原来占有的资源。
  • 打破环路等待条件:实现资源有序分配策略,将系统的所有资源统一编号,所有进程只能采用按序号递增的形式申请资源。

13.为什么不建议使用Executor静态工程来创建线程池?

阿里巴巴Java开发手册,明确指出不允许使用Executors静态工厂构建线程池
原因是线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors返回的线程池对象的弊端如下:
1:FixedThreadPool 和 SingleThreadPool:
允许的请求队列(底层实现是LinkedBlockingQueue)长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM
2:CachedThreadPool 和 ScheduledThreadPool
允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

14.如何创建线程池?

调用ThreadPoolExecutor的构造函数来自己创建线程池。在创建的同时,给BlockQueue指定容量就可以了。

private static ExecutorService executor = new ThreadPoolExecutor(10,10,60L, TimeUnit.SECONDS,
        new ArrayBlockingQueue(10));

15.线程池常用的参数有哪些?

  • corePoolSize:核心线程数量,会一直存在,除非allowCoreThreadTimeOut设置为true
  • maximumPoolSize:线程池允许的最大线程池数量
  • keepAliveTime:线程数量超过corePoolSize,空闲线程的最大超时时间
  • unit:超时时间的单位
  • workQueue:工作队列,保存未执行的Runnable 任务
  • threadFactory:创建线程的工厂类
  • handler:当线程已满,工作队列也满了的时候,会被调用。被用来实现各种拒绝策略。

16.常用的线程池有哪些?

  • newSingleThreadExecutor
    单个线程的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务
  • newFixedThreadExecutor(n)
    固定数量的线程池,每提交一个任务就是一个线程,直到达到线程池的最大数量,然后后面进入等待队列直到前面的任务完成才继续执行
  • newCacheThreadExecutor(推荐使用)
    可缓存线程池,当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60秒无执行)的线程,当有任务来时,又智能的添加新线程来执行。
  • newScheduleThreadExecutor
    大小无限制的线程池,支持定时和周期性的执行线程

17.说一下ThreadPoolExecutor线程池的执行流程是什么样的?

  • 线程池的创建: 首先,创建一个 ThreadPoolExecutor 实例,并配置线程池的参数,包括核心线程数、最大线程数、线程存活时间、任务队列等。这些参数决定了线程池的行为。

  • 任务提交: 将任务提交给线程池执行。任务可以是 Runnable 或 Callable 接口的实现类。线程池会管理任务的执行。

  • 核心线程处理任务: 如果当前线程池中的线程数量没有达到核心线程数,那么会创建新的核心线程来执行任务。每个任务都会分配一个线程来处理。

  • 任务队列存储任务: 如果线程池中的线程数已经达到核心线程数,但是任务继续提交,那么这些任务会被存储在任务队列中等待执行。任务队列可以是 LinkedBlockingQueue、ArrayBlockingQueue 等类型,具体根据线程池配置而定。

  • 最大线程处理任务: 如果任务队列已满,且线程池中的线程数量还没有达到最大线程数,那么线程池会创建新的线程来处理任务,直到线程数达到最大线程数。

  • 饱和策略处理任务: 如果线程池中的线程数已经达到最大线程数,而且任务队列也已满,那么会根据设置的饱和策略来处理任务。饱和策略可以是丢弃任务、抛出异常、阻塞等等,具体取决于线程池的配置。

  • 任务执行: 线程池中的线程会从任务队列中取出任务并执行。执行完成后,线程可能会被回收(如果超过核心线程数,根据线程存活时间和空闲时间策略),或者继续执行其他任务。

  • 任务完成: 任务执行完成后,线程池可以将结果返回给调用方(对于 Callable 任务),或者什么都不返回(对于 Runnable 任务)。

  • 线程池维护: 线程池会根据配置自动维护线程数量,例如根据线程存活时间和空闲时间策略来回收或创建线程。

  • 关闭线程池: 当不再需要线程池时,应该调用 shutdown() 或 shutdownNow() 方法来关闭线程池,释放资源。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

穿越撒哈拉:中国跨境电商的非洲冒险之旅

非洲,这片古老而神秘的大陆,一直以来都是探险者和冒险家的梦想之地。然而,近年来,中国的跨境电商企业也开始将目光投向了这片充满机遇的土地,但他们的目标不再是黄金和珍宝,而是一个更为宝贵的财富&#xf…

创建线程的方式打开记事本

更好的阅读体验 \huge{\color{red}{更好的阅读体验}} 更好的阅读体验 今天操作系统课老师讲到进程,提出了一个有趣的小实验:能否以系统调用的方式利用 Windows 创建进程的系统调用函数来打开一个软件。闲着蛋疼的我立马来了兴趣,姑且写一个玩…

跨平台编程开发工具Xojo 2023 Release mac中文版功能介绍

Xojo mac是一款跨平台的软件开发工具,它允许开发人员使用一种编程语言来创建应用程序,然后可以在多个操作系统上运行。Xojo 2023是Xojo开发工具的最新版本,它提供了许多功能和改进,以帮助开发人员更轻松地构建高质量的应用程序。 …

【洛谷】P2004 领地选择

原题链接:https://www.luogu.com.cn/problem/P2004 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 整体思路:二维前缀和 (模板在这https://blog.csdn.net/m0_62531913/article/details/132712831?spm1001.2014.30…

[安洵杯 2019]easy_web md5强碰撞 preg_match绕过

比较简单 url一看就存在一个cmd 和 base64 我们尝试给cmd传递参数 但是没有效果 所以我们就去看看 img里面是什么 直接放到瑞士军刀看看 知道了加密方法 我们去看看能不能返回 index.php代码 TmprMlpUWTBOalUzT0RKbE56QTJPRGN3 返回了 接下俩就是代码审计了 <?php erro…

Python ---使用Fake库向clickhouse造数据小案例

每次insert太麻烦了 先在clickhosue中建表 test_user表 CREATE TABLE dwh.test_user (name String,age Int32,address String,phone String,email String ) ENGINE MergeTree() ORDER BY name; 此时表中暂无数据 用Python脚本来造一些数据 from faker import Faker from c…

Matlab图像处理-灰度级到彩色空间变换法

灰度级到彩色空间变换法 灰度图像转换为具有多种颜色渐变的连续彩色图像。该方法的基本概念是对任意输入像素的灰度级进行三个独立的变换。然后&#xff0c;将三个变换结果分别发送到彩电电视监视器的红、绿、蓝通道。该方法产生一个合成图像&#xff0c;其彩色内容受变换函数…

地球+卫星运动轨迹

由于工作中&#xff0c; 需要追踪卫星&#xff0c; 记录一下最近的工作成果&#xff0c; 分别有俩个方案&#xff0c; 一个是基于市面上主流的Threejs&#xff0c; 另外一个是基于Cesium&#xff0c; 还尝试过使用&#xff0c; Planetary.js&#xff0c; 效果其实还蛮好&#x…

vSphere 7.0 Update 3提示vCLS虚拟机没有兼容的主机的问题即物理机开启CPU “Monitor/Mwait”功能的方法

本文讲解在华为物理服务器上开启CPU "Monitor/Mwait"功能的方法&#xff0c;以解决vSphere 7.0 Update 3平台上vCLS代理虚拟机提示没有与虚拟机兼容的主机&#xff0c;无法开机&#xff0c;且一直尝试启动反复告警的问题。 一、问题实况 1、VC升级到7.0.3后&#x…

Linux系统编程(三):进程

参考引用 UNIX 环境高级编程 (第3版)黑马程序员-Linux 系统编程 1. 进程相关概念 1.1 程序和进程 程序&#xff0c;是指编译好的二进制文件&#xff0c;在磁盘上&#xff0c;不占用系统资源 (CPU、内存、打开的文件、设备、锁…) 程序 → 剧本 (纸) 进程与操作系统原理联系紧…

基于Yolov8的野外烟雾检测(3):动态蛇形卷积(Dynamic Snake Convolution),实现暴力涨点 | ICCV2023

目录 1.Yolov8介绍 2.野外火灾烟雾数据集介绍 3.Dynamic Snake Convolution 3.1 Dynamic Snake Convolution加入到yolov8 4.训练结果分析 5.系列篇 1.Yolov8介绍 Ultralytics YOLOv8是Ultralytics公司开发的YOLO目标检测和图像分割模型的最新版本。YOLOv8是一种尖端的、最…

ggplot2做图(填坑中)

数据 df <- data.frame(x 1:10, y 1:10, f c(rep("A", 5), rep("B", 5))) 做图 1. 散点图 (scatter plot) # scatter plot scatter_plot <- function(df, metadata) {identical(rownames(df), rownames(metadata))data <- cbind(df, metada…

JavaScript系列从入门到精通系列第一篇:JavaScript语言简介和它代码初体验

一&#xff1a;简介 1&#xff1a;起源 JavaScript诞生于1995年&#xff0c;它的出现主要是用于处理网页中的前端验证&#xff0c; 所谓的前端验证&#xff0c;就是指检查用户输入的内容是否符合一定的规则。 2&#xff1a;简史 JavaScript是由网景公司发明&#xff0c;起初命…

安全测试:文件上传漏洞检测

文件上传漏洞 是一种安全漏洞&#xff0c;允许攻击者将恶意文件上传到目标服务器&#xff0c;从而可能导致恶意代码执行、服务器瘫痪或其他不安全的情况。 假设您正在测试一个网络应用程序&#xff0c;该应用程序允许用户上传文件&#xff0c;例如用户头像。你怀疑应用程序可能…

QT实现相关功能

1、文本的保存 mianwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include<QFontDialog> //字体对话框 #include<QFont> //字体类 #include<QMessageBox> //消息对话框 #…

伦敦银交易所数据全面吗?

据伦敦市场的数据显示&#xff0c;每天平均有超过1900万盎司的黄金和1.7亿盎司的白银交易在发生&#xff0c;而且实际的数量可能是这个数字几倍&#xff0c;因为许多的交易发生都在私人市场&#xff0c;不会产生交易信息报告&#xff0c;所以我们难以准确评估市场上所有的金银交…

ROS2 驱动思岚G4雷达(ydlidar)- Rviz显示

记录G4雷达的配置 系统环境为&#xff1a;Ubuntu22.04 配置步骤 1、安装雷达SDK 2、构建 G4 雷达 ROS2 项目工程文件 3、使用Rviz可视化界面显示 1、安装雷达SDK 1.1 安装CMake YDLidar SDK需要CMake 2.8.2作为依赖项 Ubuntu 18.04或者Ubuntu 22.04 sudo apt install cmak…

【AI语言模型】阿里推出音视频转文字引擎

一、前言 阿里的音视频转文字引擎可以正式使用,用户可体验所有AI功能,含全文概要、章节速览、发言总结等高阶AI功能。通过阿里云主账号登录,可享受以下权益: 每日登录,自动获得2小时转写时长; 每邀请1名好友注册并登录通,邀请者可获得2小时转写时长; 输入口令即可获得…

3288S Android11 适配红外遥控功能(超详细)

目录 一、rk3288平台红外遥控介绍二、原理图分析三、配置设备树并使能红外遥控功能四、打开红外打印功能&#xff0c;查看红外遥控的用户码和键值五、将查看到的红外遥控用户码和键值添加到设备树和.kl文件六、Android红外遥控.kl文件映射知识和使用添加新的.kl文件七、补充&am…

Learn Prompt-Prompt 高级技巧:思维链 Chain of Thought Prompting

Jason Wei等作者对思维链的定义是一系列的中间推理步骤&#xff08; a series of intermediate reasoning steps &#xff09;。目的是为了提高大型语言模型&#xff08;LLM&#xff09;进行复杂推理的能力。 思维链通常是伴随着算术&#xff0c;常识和符号推理等复杂推理任务出…