面试题004-Java-Java多线程(下)

面试题004-Java-Java多线程(下)

这里写目录标题

  • 面试题004-Java-Java多线程(下)
    • 题目自测
    • 题目答案
      • 1. synchronized 关键字的作用?
      • 2. volatile 关键字的作用?
      • 3. synchronized 和 volatile 的区别?
      • 4. synchronized 和 ReentrantLock 的区别?
      • 5. ThreadLocal有什么用?
      • 6. 线程池有什么用?为什么不推荐使用内置线程池?
      • 7. 如何自定义线程池?
      • 8. Java线程池有哪些参数?阻塞队列有几种?拒绝策略有几种?
      • 9. 线程池处理任务的流程了解吗?
      • 10. 如何给线程池命名?为什么建议给线程池命名?
    • 参考资料

题目自测

  • 1. synchronized 关键字的作用?
  • 2. volatile 关键字的作用?
  • 3. synchronized 和 volatile 的区别?
  • 4. synchronized 和 ReentrantLock 的区别?
  • 5. ThreadLocal有什么用?
  • 6. 线程池有什么用?为什么不推荐使用内置线程池?
  • 7. 如何自定义线程池?
  • 8. Java线程池有哪些参数?阻塞队列有几种?拒绝策略有几种?
  • 9. 线程池处理任务的流程了解吗?
  • 10. 如何给线程池命名?为什么建议给线程池命名?

题目答案

1. synchronized 关键字的作用?

答:在Java中synchronized关键字用于实现线程同步,主要解决是多个线程之间访问相同资源不会发生数据不一致的问题。它可以作用于方法或代码块上,以保证同一时间只有一个线程可以执行被同步的方法或代码块。

  • 同步实例方法: 表示该方法在同一时间只能由一个线程访问同一个实例。

    public class SynchronizedExample {public synchronized void synchronizedMethod() {// 同步代码}
    }
    
  • 同步静态方法:表示该方法在同一时间只能由一个线程访问同一个类的所有实例。

    public class SynchronizedExample {public static synchronized void synchronizedStaticMethod() {// 同步代码}
    }
    
  • 同步代码块:表示该代码块在同一时间只能由一个线程访问该对象。

    public class SynchronizedExample {private final Object lock = new Object();public void synchronizedBlock() {synchronized (this) {// 同步代码}}
    }
    

2. volatile 关键字的作用?

答:在Java中volatile关键字用于声明变量的可见性和防止指令重排,从而提供一种轻量级的同步机制。
在可见性方面,用volatile修饰的变量,来确保一个线程对该变量的修改对其他线程立即可见。
在防止指令重排方面,volatile会禁止JVM对变量操作的指令进行重新排序。

3. synchronized 和 volatile 的区别?

答:synchronized和volatile两个关键字都用于实现线程同步的机制。

  • volatile是线程同步的轻量级实现,volatile性能比synchronized要好。volatile关键字只能用于变量,而synchronized关键字可以修饰方法和代码块。
  • volatile能保证数据的可见性,但不能保证数据的原子性。synchronized两者都能保证。
  • volatile主要解决变量在多个线程之间的可见性,而synchronize解决的是多个线程之间访问资源的同步性。

4. synchronized 和 ReentrantLock 的区别?

答:synchronized和ReentrantLock都是Java中用于实现线程同步的机制,并且都是可重入锁。

  • synchronized:
    • 是Java语言的内置关键字,用于对代码块或方法进行同步。
    • 简单易用,直接在方法或代码块上使用即可。
    • 由JVM实现,使用方便,但功能较为有限。
  • ReentrantLock:
    • ReentrantLock是java.util.concurrent.locks包中的类,提供了更灵活和丰富的锁机制(响应中断、尝试获取锁、使用条件变量等)。
    • 需要显示的加锁和解锁,通过代码来控制锁的获取和释放。
    • 由Java库实现,功能强大,灵活性高。

5. ThreadLocal有什么用?

答:ThreadLocal在Java中用于创建线程局部变量,确保每个变量都有自己的独立副本变量,从而避免多线程共享一个变量带来的线程安全问题,同时提高了并发性能。然而在使用ThreadLocal时需要注意内存泄露问题,由于ThreadLocal变量的生命周期与线程线相同,如果线程池中线程长时间不被销毁,而ThreadLocal变量没有被正确移除,可能会导致内存泄露问题,因此建议在不再使用ThreadLocal变量时显示调用remove()方法。
它的使用场景有用户会话管理、数据库连接管理、事物管理等。

6. 线程池有什么用?为什么不推荐使用内置线程池?

答:Java中的线程池是一种基于池化技术设计用于执行异步任务的框架,它维护了一定数量的线程,避免频繁地创建和销毁线程带来的性能开销和资源浪费。他的主要作用是提高资源复用、提高系统稳定性、便于管理和提供灵活的并发策略。

不推荐使用内置线程池的主要原因是内置线程池等配置选项有限、不能满足所有的应用场景的需求。Java库中提供了几种预定义线程的实现,如Executors类中的newFixedThreadPoolnewCacheThreadPoolnewSingleThreadExecutor等。

  • FixedThreadPool 和 SingleThreadExecutor 使用无界队列(LinkedBlockingQueue),在任务提交速度超过执行速度时,任务队列可能无限增长,导致内存耗尽。
  • CacheThreadPool 使用无界线程池,在高并发下可能会创建大量线程、导致系统资源耗尽。未被回收的线程可能会长时间占用资源,造成线程泄漏问题。

7. 如何自定义线程池?

答:在Java中,自定义线程池可以通过ThreadPoolExecutor类来实现。ThreadPoolExecutor提供了丰富的配置选项,如核心线程数(corePoolSize)、最大线程数(maximumPoolSize)、任务队列(workQueue)和拒绝策略(rejectedExecutionHandler)等,可以根据具体需求进行灵活配置。

import java.util.concurrent.ArrayBlockingQueue;  
import java.util.concurrent.ThreadPoolExecutor;  
import java.util.concurrent.TimeUnit;  public class CustomThreadPoolExample {  public static void main(String[] args) {  // 核心线程数 :线程池在空闲时保留的线程数,即使没有任务需要处理。int corePoolSize = 5;  // 最大线程数 :线程池允许创建的最大线程数。int maximumPoolSize = 10;  // 非核心线程空闲存活时间 :当线程数超过核心线程数时,多余的空闲线程的存活时间。long keepAliveTime = 1L;  // 时间单位 : 空闲线程存活时间的时间单位。TimeUnit unit = TimeUnit.SECONDS;  // 任务队列 :用于保存等待执行任务的队列。ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(100);  // 线程工厂 : 用于创建新线程。ThreadFactory threadFactory = Executors.defaultThreadFactory();  // 拒绝策略 : 当线程池和队列都满时,如何处理新任务RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();  // 创建ThreadPoolExecutor  ThreadPoolExecutor executor = new ThreadPoolExecutor(  corePoolSize,  maximumPoolSize,  keepAliveTime,  unit,  workQueue,  threadFactory,  handler  );  // 提交任务  for (int i = 0; i < 15; i++) {  int taskId = i;  executor.execute(() -> {  System.out.println(Thread.currentThread().getName() + " is processing " + taskId);  try {  // 模拟任务执行时间  Thread.sleep(1000);  } catch (InterruptedException e) {  Thread.currentThread().interrupt();  }  });  }  // 关闭线程池(不再接受新任务,但已提交的任务会继续执行)  executor.shutdown();  // 等待所有任务完成  while (!executor.isTerminated()) {  // 等待一段时间  }  System.out.println("All tasks completed.");  }  
}

8. Java线程池有哪些参数?阻塞队列有几种?拒绝策略有几种?

答:
线程池的参数

  • corePoolSize(核心线程数):线程池中始终保留的线程数量,即使这些线程处于空闲状态。
  • maximumPoolSize(最大线程数):线程池中允许创建的最大线程数量。当任务队列已满且当前线程数小于最大线程数时,会创建新线程来处理任务。
  • keepAliveTime(空闲线程存活时间):当线程池中的线程数超过核心线程数时,多余的空闲线程在终止前等待新任务的最长时间。
  • timeUnit(时间单位):keepAliveTime 参数的时间单位。常见值包括 TimeUnit.SECONDS、TimeUnit.MILLISECONDS 等。
  • workQueue(任务队列):用于保存等待执行任务的队列l。
  • threadFactory(线程工厂):用于创建新线程。
  • rejectedExecutionHandler(拒绝策略):当线程池和队列都满时,如何处理新任务。

阻塞队列

  • ArrayBlockingQueue:一个基于数组的有界阻塞队列。按FIFO(先进先出)顺序保存任务。
  • LinkedBlockingQueue:一个基于链表的可选有界阻塞队列。通常用于无限制的任务队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等待一个相应的移除操作。
  • PriorityBlockingQueue:一个基于优先级的无限阻塞队列。任务按照优先级顺序执行。
  • DelayQueue:一个基于优先级队列的无界阻塞队列,只有在延迟期满时才能从队列中取走元素。

拒绝策略

  • AbortPolicy(默认策略):抛出 RejectedExecutionException 异常,阻止系统正常工作。
  • CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务。这种策略会降低新任务的提交速度,从而减轻线程池的负载。
  • DiscardPolicy:直接丢弃任务,不抛出异常。如果允许任务丢失,这种策略可以用于避免系统过载。
  • DiscardOldestPolicy:丢弃队列中最旧的任务(即即将执行的任务),然后重新尝试提交新任务。

9. 线程池处理任务的流程了解吗?

答:线程池处理任务的流程可以总结为:提交任务、检查核心线程数、任务队列处理、非核心线程创建、执行任务以及线程回收。

  1. 通过submit()或execute()方法提交任务
  2. 检查核心线程数,如果当前线程数少于核心线程数,那么就创建新的核心线程来执行任务。如果当前线程数已达到核心线程数,将任务放入任务队列。
  3. 如果任务队列没有满,将任务队列继续放入队列。如果任务队列已满,检查当前线程数是否小于最大线程数。
  4. 如果当前线程数小于最大线程数,创建新的非核心线程执行任务,如果当前线程已经达到了最大线程数,执行拒绝策略。
  5. 线程从任务队列取出任务执行。
  6. 线程池中的非核心线程在完成任务后不会立即销毁,进入保持存活状态,只有当这些线程在空闲时间超过keepAliveTime后被回收。

10. 如何给线程池命名?为什么建议给线程池命名?

答:要给线程池中的线程命名,可以自定义一个 ThreadFactory,在创建线程时设置线程名称。

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;/*** 线程工厂,它设置线程名称,有利于我们定位问题。*/
public final class NamingThreadFactory implements ThreadFactory {private final AtomicInteger threadNum = new AtomicInteger();private final String name;/*** 创建一个带名字的线程池生产工厂*/public NamingThreadFactory(String name) {this.name = name;}@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r);t.setName(name + " [#" + threadNum.incrementAndGet() + "]");return t;}
}

在 Java 中,为线程池中的线程命名是一种良好的实践。命名线程有助于调试和监控,使得可以轻松识别和跟踪线程的行为和状态。

参考资料

  • JavaGuide
  • 牛客网-Java面试宝典

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

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

相关文章

成人高考本科何时报名-深职训学校帮您规划学习之路

你有想过继续深造自己的学历吗&#xff1f;也许你已经工作多年&#xff0c;但总觉得学历是一块心病&#xff0c;想要通过成人高考本科来提升自己。不用着急&#xff0c;今天我们来聊一聊成人高考本科的报名时间&#xff0c;以及深职训学校如何帮助你顺利完成报名。 深圳成人高…

LeetCode-刷题记录-滑动窗口合集(本篇blog会持续更新哦~)

一、滑动窗口概述 滑动窗口&#xff08;Sliding Window&#xff09;是一种用于解决数组&#xff08;或字符串&#xff09;中子数组&#xff08;或子串&#xff09;问题的有效算法。 Sliding Window核心思想&#xff1a; 滑动窗口技术的基本思想是维护一个窗口&#xff08;一般…

怎样在Python中使用oobabooga的API密钥,通过端口5000获取模型列表的授权

题意&#xff1a; oobabooga-textgen-web-ui how to get authorization to view model list from port 5000 via the oobas api-key in python 怎样在Python中使用oobabooga的API密钥&#xff0c;通过端口5000获取模型列表的授权 问题背景&#xff1a; I wish to extract an…

fastapi+vue3前后端分离开发第一个案例整理

开发思路 1、使用fastapi开发第一个后端接口 2、使用fastapi解决cors跨域的问题。cors跨域是浏览器的问题&#xff0c;只要使用浏览器&#xff0c;不同IP或者不同端口之间通信&#xff0c;就会存在这个问题。前后端分离是两个服务&#xff0c;端口不一样&#xff0c;所以必须要…

PCA和PCoA分析的python代码

主成分分析(PCA)和主坐标分析(PCoA)都是数据降维和可视化的常用方法,但它们在适用场景和计算方法上有一些重要区别。 主成分分析(PCA) 定义: PCA是一种线性降维方法,通过正交变换将原始数据转化为一组线性不相关的变量(主成分)。这些主成分是数据中方差最大的方向。…

XLSX + LuckySheet + LuckyExcel实现前端的excel预览

文章目录 功能简介简单代码实现效果参考 功能简介 通过LuckyExcel的transformExcelToLucky方法&#xff0c; 我们可以把一个文件直接转成LuckySheet需要的json字符串&#xff0c; 之后我们就可以用LuckySheet预览excelLuckyExcel只能解析xlsx格式的excel文件&#xff0c;因此对…

.NET 漏洞分析 | 某ERP系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

Java中s-EJB 与 e-EJB的区别

在Java中&#xff0c;关于“s-EJB”与“e-EJB”的区分&#xff0c;实际上可能存在一定的误解或混淆&#xff0c;因为在标准的EJB&#xff08;Enterprise JavaBeans&#xff09;术语中&#xff0c;并没有直接称为“s-EJB”和“e-EJB”的明确分类。然而&#xff0c;为了尝试解答这…

【Postman gRPC测试全攻略】探索微服务通信的新纪元

标题&#xff1a;【Postman gRPC测试全攻略】探索微服务通信的新纪元 gRPC是一种高性能、开源和通用的RPC框架&#xff0c;由Google主导开发&#xff0c;它使用Protocol Buffers作为接口描述语言和消息交换格式。Postman作为API开发的利器&#xff0c;也提供了对gRPC服务的测试…

封装2个函数

1 #include "key1.h"2 //封装EXTI章节函数3 void hal_exti_init(int exti,unsigned int i)4 {5 switch(exti)6 {7 case 9:8 //使能GPIOF外设时钟9 RCC->MP_AHB4ENSETR | (0x1<<5);10 //将PF9设置为输出模式11 …

MyBatis(22)如何在 MyBatis 中使用注解而不是 XML 映射文件

在 MyBatis 中&#xff0c;使用注解而不是 XML 映射文件来进行 SQL 映射是一种更为简洁直观的方式&#xff0c;尤其适用于 SQL 语句较少的场景。通过注解&#xff0c;开发者可以直接在接口方法上声明 SQL 语句&#xff0c;这样可以减少项目中的配置文件数量&#xff0c;使得项目…

学习笔记——动态路由——OSPF(认证)

十二、OSPF邻居认证 1、OSPF邻居认证概述 链路是路由器接口的另一种说法&#xff0c;因此OSPF也称为接口状态路由协议。OSPF通过路由器之间通告网络接口的状态来建立链路状态数据库&#xff0c;生成最短路径树&#xff0c;每个OSPF路由器使用这些最短路径构造路由表。 OSPF认…

基于Vue框架实现的记事本

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>懒人记事本</title><style>body {fo…

深度网络现代实践 - 深度前馈网络之反向传播和其他的微分算法篇

序言 反向传播&#xff08;Backpropagation&#xff0c;简称backprop&#xff09;是神经网络训练过程中最关键的技术之一&#xff0c;尤其在多层神经网络中广泛应用。它是一种与优化方法&#xff08;如梯度下降法&#xff09;结合使用的算法&#xff0c;用于计算网络中各参数的…

大数据面试题之数仓(1)

目录 介绍下数据仓库 数仓的基本原理 数仓架构 数据仓库分层(层级划分)&#xff0c;每层做什么?分层的好处? 数据分层是根据什么? 数仓分层的原则与思路 知道数仓建模常用模型吗?区别、优缺点? 星型模型和雪花模型的区别?应用场景?优劣对比 数仓建模有哪些方式…

【Symfony社区全接触】深入探索文档与支持资源

标题&#xff1a;【Symfony社区全接触】深入探索文档与支持资源 Symfony是一个强大的PHP框架&#xff0c;拥有一个活跃的开发者社区和丰富的文档资源。这些资源对于学习和使用Symfony至关重要。本文将详细介绍Symfony的文档和社区支持&#xff0c;包括官方文档、社区论坛、邮件…

如何计算弧线弹道的落地位置

1&#xff09;如何计算弧线弹道的落地位置 2&#xff09;Unity 2021 IL2CPP下使用Protobuf-net序列化报异常 3&#xff09;编译问题&#xff0c;用Mono可以&#xff0c;但用IL2CPP就报错 4&#xff09;Wwise的Bank在安卓上LoadBank之后&#xff0c;播放没有声音 这是第393篇UWA…

02 数据加工层 如何搭建用户与内容的标准规范体系

你好&#xff0c;我是周大壮。 01 讲我们提到了个性化流量分发体系的四个阶段&#xff0c;并着重讲解了数据采集阶段的内容。那么&#xff0c;这一讲我们主要围绕数据加工阶段的内容进行详细讲解。 在课程开始之前&#xff0c;我们先举一个场景进行说明。 近年来&#xff0c…

静态方法与实例方法的区别

静态方法与实例方法的区别 1、静态方法&#xff08;Static Methods&#xff09;1.1 调用方式1.2 访问权限 2、实例方法&#xff08;Instance Methods&#xff09;2.1 调用方式2.2 访问权限 3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1…

大数据面试题之数仓(2)

目录 维度表和事实表的区别? 什么是ER模型? OLAP、OLTP解释(区别)三范式是什么&#xff0c;举些例子 维度设计过程&#xff0c;事实设计过程 维度设计中有整合和拆分&#xff0c;有哪些方法&#xff0c;并详细说明 事实表设计分几种&#xff0c;每一种都是如何在业…