持续总结中!2024年面试必问 100 道 Java基础面试题(四十五)

上一篇地址:持续总结中!2024年面试必问 100 道 Java基础面试题(四十四)-CSDN博客

八十九、在Java中,什么是线程局部变量(ThreadLocal变量)?

在Java中,ThreadLocal变量是一种特殊的变量,它为每个线程提供了一个独立副本的变量。当一个线程访问通过ThreadLocal对象发布的变量时,它实际上是访问该变量在当前线程的副本,而不是共享的原始副本。这种方式可以避免在多线程环境下的同步问题,因为每个线程只操作自己的数据副本。

线程局部变量的主要特点:

  1. 线程隔离:每个线程通过ThreadLocal访问到的变量是隔离的,互不影响。

  2. 存储机制ThreadLocal内部使用ThreadLocalMap来存储每个线程的局部变量副本。这个映射是线程私有的,键是ThreadLocal对象,值是线程局部变量的副本。

  3. 内存泄漏:由于ThreadLocalMap的生命周期与线程相同,如果ThreadLocal对象被回收,但是ThreadLocalMap中仍然有对它的引用,就可能导致内存泄漏。因此,通常推荐在使用完ThreadLocal后调用remove()方法来清除线程局部变量。

  4. 初始值:可以通过ThreadLocalwithInitial方法提供初始值函数,为每个线程的局部变量提供初始值。

  5. 更新和访问:线程可以通过调用set(T value)方法来更新自己的局部变量副本,通过get()方法来访问自己的副本。

使用场景:

  1. 线程特定的配置:当需要为每个线程提供特定的配置信息时,可以使用ThreadLocal来存储这些信息。

  2. 用户会话信息:在web应用中,可以为每个用户请求创建一个线程局部的用户会话对象,存储用户信息。

  3. 线程安全的单例:可以利用ThreadLocal实现线程安全的单例模式,每个线程都有自己的单例实例。

  4. 数据库连接和事务管理:在某些情况下,可以将数据库连接或事务管理对象存储在ThreadLocal中,确保每个线程使用自己的数据库连接。

示例代码:

public class ThreadLocalExample {private static final ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> "default value");public static void main(String[] args) {// 线程1new Thread(() -> {threadLocal.set("value for thread 1");System.out.println("Thread 1: " + threadLocal.get());}).start();// 线程2new Thread(() -> {threadLocal.set("value for thread 2");System.out.println("Thread 2: " + threadLocal.get());}).start();}
}

在这个示例中,两个线程各自设置了ThreadLocal变量的值,并且只能访问到自己的值,互不影响。

注意事项:

  • 由于ThreadLocal变量是线程私有的,因此它们不能被synchronizedReentrantLock等同步机制保护,因为它们不存在线程间的竞争条件。
  • 使用ThreadLocal时,要注意内存泄漏的问题,尤其是在线程池中,因为线程可能会复用,而ThreadLocal变量如果没有及时清理,可能会导致长时间占用内存。
  • 在使用ThreadLocal时,应该尽量在不需要时及时移除对应的线程局部变量,以避免潜在的内存泄漏风险。

ThreadLocal为多线程环境中的变量隔离提供了一种简单而高效的方式,但在使用时也需要考虑到内存泄漏等潜在问题。

九十、如何实现Java程序的并发执行?

在Java中实现并发执行主要涉及以下几个方面:

1. 线程(Thread)

线程是实现并发执行的基本单位。在Java中,可以通过继承Thread类或实现Runnable接口来创建线程。

  • 继承Thread类:创建一个类继承Thread类,并重写run()方法。
class MyThread extends Thread {public void run() {// 线程执行的代码}
}// 实例化并启动线程
MyThread t = new MyThread();
t.start();
  • 实现Runnable接口:创建一个类实现Runnable接口,并实现run()方法。
class MyRunnable implements Runnable {public void run() {// 线程执行的代码}
}// 使用Thread类创建线程并启动
Thread t = new Thread(new MyRunnable());
t.start();

2. 线程池(ThreadPool)

线程池用于管理线程资源,它可以有效地控制并发执行的线程数量,提高性能,并减少系统资源的消耗。

  • Executor框架:Java提供了java.util.concurrent包,其中包含了Executor框架,用于创建和管理线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池
executor.submit(() -> {// 并发执行的任务
});
executor.shutdown(); // 关闭线程池

3. 同步(Synchronization)

在多线程环境下,为了避免线程间的数据竞争和状态不一致,需要使用同步机制。

  • 同步代码块:使用synchronized关键字来同步一段代码块。
synchronized (obj) {// 需要同步的代码
}
  • 同步方法:在方法声明中使用synchronized关键字,使整个方法成为同步方法。
public synchronized void myMethod() {// 方法体
}

4. 并发集合(Concurrent Collections)

Java提供了一组线程安全的集合类,位于java.util.concurrent包中,如ConcurrentHashMapConcurrentLinkedQueue等。

import java.util.concurrent.ConcurrentHashMap;ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
map.put("key", "value"); // 线程安全的put操作

5. 并发工具类(Concurrent Utilities)

Java提供了一些并发工具类,如CountDownLatchCyclicBarrierSemaphore等,用于控制并发流程。

  • CountDownLatch:允许一个或多个线程等待一组事件的发生。
CountDownLatch latch = new CountDownLatch(1);
// 线程执行任务
latch.countDown(); // 事件完成,减少计数
latch.await(); // 等待事件完成

6. 原子变量(Atomic Variables)

Java提供了一组原子变量类,如AtomicIntegerAtomicLong等,它们利用CAS(Compare-And-Swap)操作来实现线程安全的变量更新。

import java.util.concurrent.atomic.AtomicInteger;AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // 原子地增加并返回当前值

7. 锁(Locks)

java.util.concurrent.locks包提供了更强大的锁机制,如ReentrantLock

import java.util.concurrent.locks.ReentrantLock;ReentrantLock lock = new ReentrantLock();
lock.lock(); // 获取锁
try {// 受保护的代码
} finally {lock.unlock(); // 释放锁
}

8. 并发异常处理

在编写并发程序时,需要特别注意异常处理,以避免线程因为未捕获的异常而意外终止。

Thread t = new Thread(() -> {try {// 可能抛出异常的代码} catch (Exception e) {// 异常处理}
});
t.start();

9. 并发设计模式

合理应用并发设计模式,如生产者-消费者模式、读写锁模式等,可以简化并发程序的逻辑,提高代码的可读性和可维护性。

实现Java程序的并发执行是一个复杂的过程,需要综合考虑资源管理、线程安全、性能优化等多个方面。正确使用Java提供的并发工具和机制,可以有效地提高程序的并发性能和稳定性。

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

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

相关文章

企业微信hook接口协议,ipad协议http,发送链接的方式邀请成员进群

发送链接的方式邀请成员进群 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"3240fde0-45e2-48c0-90e8-cb098d0ebe43","roomid":10696052955013729, "vids":[788130334…

Flutter 中的 CircleAvatar 小部件:全面指南

Flutter 中的 CircleAvatar 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;CircleAvatar 是一个用于显示头像的圆形控件&#xff0c;通常包含一个图标、图片或者一个简单的文本字符。它在设计上与 Material Design 指南中的头像规范相匹配&#xff0c;常用于展示用户信…

C# 常用汇总

时间处理 public static class DateTimeHelper{/// <summary>/// 获取当前时间戳&#xff08;Unix时间戳&#xff09; /// </summary>/// <returns></returns>public static long GetCurrentUnixTimestamp(){DateTimeOffset offset DateTimeOffset.…

Qt---文件系统

一、基本文件操作 1. QFile对文件进行读和写 QFile file( path 文件路径) 读&#xff1a; file.open(打开方式) QlODevice::readOnly 全部读取->file.readAll()&#xff0c;按行读->file.readLine()&#xff0c;atend()->判断是否读到文件尾 …

Java网络编程基础

Java网络编程基础主要涉及进程间通信、网络通信协议、IP地址和端口以及Java提供的网络应用编程接口等核心概念。 进程间通信是Java网络编程的基础。进程是运行中的程序&#xff0c;而进程间通信则是指不同进程之间进行数据交换和共享信息的过程。在Java中&#xff0c;进程间的…

STM32存储左右互搏 USB接口FATS文件读写U盘

STM32存储左右互搏 USB接口FATS文件读写U盘 STM32的USB接口可以例化为Host主机从而对U盘进行操作。SD卡/MicroSD/TF卡也可以通过读卡器转换成U盘使用。这里介绍STM32CUBEIDE开发平台HAL库实现U盘FATS文件访问的例程。 USB接口介绍 常见的USB接口电路部分相似而有不同的连接器…

K8S -----二进制搭建 Kubernetes v1.20

目录 一、准备环境 1.1 修改主机名 1.2 关闭防火墙&#xff08;三台一起&#xff0c;这里只展示master01&#xff09; 1.3 在master添加hosts&#xff08;依旧是三台一起&#xff09; 1.4 调整内核参数并开启网桥模式 二、部署docker引擎 三、部署 etcd 集群 1.在mast…

15.JUC原子类

文章目录 JUC原子类1.JUC中的Atomic原子操作包1.1. 基本原子类&#xff08;Basic Atomic Classes&#xff09;1.2. 数组原子类&#xff08;Array Atomic Classes&#xff09;1.3. 引用原子类&#xff08;Reference Atomic Classes&#xff09;4. 字段更新原子类&#xff08;Fie…

StackQueue+泛型简单理解

&#x1f341; 个人主页&#xff1a;爱编程的Tom&#x1f4ab; 本篇博文收录专栏&#xff1a;Java专栏&#x1f449; 目前其它专栏&#xff1a;c系列小游戏 c语言系列--万物的开始_ &#x1f389; 欢迎 &#x1f44d;点赞✍评论⭐收藏&#x1f496;三连支持一…

ddpm Denoising Diffusion Probabilistic Model 学习笔记

目录 Stable Diffusion 文章的贡献抽象出来就两个 潜空间上做扩散生成 ddpm(Denoising Diffusion Probabilistic Model)学习笔记 算法原理 unet预测噪声 unet推理过程 重参数化技巧 &#xff08;1&#xff09;利用前一时刻的 xt-1 得到任意时刻的噪声图片 xt&#xff…

LeetCode2215找出两数组的不同

题目描述 给你两个下标从 0 开始的整数数组 nums1 和 nums2 &#xff0c;请你返回一个长度为 2 的列表 answer &#xff0c;其中&#xff1a;answer[0] 是 nums1 中所有 不 存在于 nums2 中的 不同 整数组成的列表。answer[1] 是 nums2 中所有 不 存在于 nums1 中的 不同 整数组…

Linux poweroff命令教程:如何实现一键关机(附实例详解和注意事项)

Linux poweroff命令介绍 poweroff命令是用来关闭系统的。当你执行这个命令时&#xff0c;它会发送一个信号给系统&#xff0c;告诉系统关闭所有的进程&#xff0c;然后关闭系统。这个命令非常有用&#xff0c;特别是在你需要远程关闭系统&#xff0c;或者你的系统没有图形用户…

Autosar架构

蓝框那种叫component&#xff0c;绿框的叫function cluster。 接口 有三种接口&#xff0c;RTE跟SWC之间链接的叫Autosar Interface&#xff0c;RTE跟BSW的Components链接是Standardized Interface&#xff0c;RTE跟BSW的services链接的是Standardized Autosar Interface。 St…

项目部署到线上proxytable代理失效nginx报404的问题

我的项目是在vue的config文件夹中的index.js中配置了接口地址 &#xff0c;本地跑的时候都能访问&#xff0c;放到线上就报404&#xff1b; module.exports {dev: {// PathsassetsSubDirectory: static,assetsPublicPath: /,proxyTable: {/xxx: {target: http://xxxxxxxx:xxx…

分享四种CAD图纸加密方法,严防盗图

在数字化时代&#xff0c;cad图纸的盗用和非法传播问题日益突出。对于企业和设计师来说&#xff0c;保护设计成果的安全性和原创性&#xff0c;采取有效的cad加密方法至关重要。本文将分享四种cad加密方法&#xff0c;帮助您严防盗图&#xff0c;保护图纸安全。 使用cad软件内…

网络协议的分类

1.概要 网络协议可以分为三类&#xff1a; 封装协议路由协议功能类协议 2.分类说明 OSPF报文直接调用_ IP协议__协议进行封装&#xff0c;以目的地址_244.0.0.5 __发送到所有的OSPF路由器? 244.0.0.1 所有主机&#xff1b;244.0.0.2 所有路由器&#xff1b;244.0.0.6 指定…

【前端每日一题】day5

JS 实现继承的几种方式 在JavaScript中&#xff0c;实现继承的几种方式包括原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承和组合式继承。 原型链继承&#xff1a; function Parent() {this.name Parent; } Parent.prototype.sayHello function() {console.…

当它还是幼生期的时候,及早离开它!

当我们有丰富的精神生活时&#xff0c;充实的知识吸收储备时&#xff0c;为自己的每一点进步而欣慰时&#xff0c;我们就不会有失败的忧虑。也不会有孤单的自怜。 没有人是弱者&#xff0c;每个人都有自己活着的方式&#xff0c;当你内心强大时&#xff0c;你会尊重每一个“弱者…

Vue+springboot的批量删除功能

vue前台 <div style"margin-bottom: 10px"><el-button type"primary" plain click"handleAdd">新增</el-button><el-button click"delBatch" type"danger" plain style"margin-left: 5px"…

Spring Cloud 背后技术详解

Spring Cloud 是基于 Spring Boot 的一套微服务架构解决方案。它为开发者提供了一系列的工具&#xff0c;用于快速构建分布式系统中的一些常见模式&#xff08;例如配置管理、服务发现、断路器等&#xff09;。Spring Cloud 利用 Spring Boot 的自动配置和独立运行能力&#xf…