当前位置: 首页 > news >正文

ThreadLocal的使用方式

1.  ThreadLocal的使用方式 

(1)  在关联数据类中创建private static ThreadLocal 

在下面的类中,私有静态 ThreadLocal 实例(serialNum)为调用该类的静态 SerialNum.get() 方法的每个

线程维护了一个“序列号”,该方法将返回当前线程的序列号。(线程的序列号是在第一次调用 SerialNum.get() 时

分配的,并在后续调用中不会更改。) 

public class SerialNum {

 // The next serial number to be assigned   

 private static int nextSerialNum = 0;   

 private static ThreadLocal serialNum = new ThreadLocal() {     protected synchronized Object initialValue() {   

 return new Integer(nextSerialNum++);   

 }   

 };   

 public static int get() {   

 return ((Integer) (serialNum.get())).intValue();   

 }   

}

另一个例子,也是私有静态 ThreadLocal 实例: 

public class ThreadContext {

  private String userId;

  private Long transactionId; 

  private static ThreadLocal threadLocal = new ThreadLocal(){ 

@Override

 protected ThreadContext initialValue() {

 return new ThreadContext(); 

 }

 }; 

 public static ThreadContext get() {

 return threadLocal.get(); 

 } 

 public String getUserId() {

 return userId; 

 } 

 public void setUserId(String userId) {

 this.userId = userId;

 } 

 public Long getTransactionId() {

 return transactionId;

 } 

 public void setTransactionId(Long transactionId) {

 this.transactionId = transactionId;

 } 

}

补充:JDKAPIThreadLocal说明。举例线程唯一标识符’

UniqueThreadIdGenerator ,大家习是结合官API 

2.  在Util类中创建ThreadLocal 

这是上面用法的扩展,即把ThreadLocal的创建放到工具类中。 

public class HibernateUtil { 
 private static Log log = LogFactory.getLog(HibernateUtil.class); 
 private static final SessionFactory sessionFactory;     //定义SessionFactory

 static {

 try {

 // 通过默认配置文件hibernate.cfg.xml创建SessionFactory
 sessionFactory = new Configuration().configure().buildSessionFactory();  } catch (Throwable ex) { 

 log.error("初始化SessionFactory失败!", ex);

 throw new ExceptionInInitializerError(ex); 

 }

 }

 //创建线程局部变量session,用来保存Hibernate的Session
 public static final ThreadLocal session = new ThreadLocal();

 /**

 * 获取当前线程中的Session

 * @return Session

 * @throws HibernateException 

 */
 public static Session currentSession() throws HibernateException {

 Session s = (Session) session.get(); 

 // 如果Session还没有打开,则新开一个Session 

 if (s == null) {

 s = sessionFactory.openSession(); 

 session.set(s);         //将新开的Session保存到线程局部变量中 

 }

 return s;

 }

 public static void closeSession() throws HibernateException {  //获取线程局部变量,并强制转换为Session类型 

 Session s = (Session) session.get(); 

 session.set(null);

 if (s != null)

 s.close();

 }

}

3.  在Runnable中创建ThreadLocal 

在线程类内部创建ThreadLocal,基本步骤如下: 

①、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间

需要隔离处理的对象xxx。 

②、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若

ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型 

③、在ThreadDemo类的run()方法中,通过调用getXxx()方法获取要操作的数据,这样可以保证每个线

程对应一个数据对象,在任何时刻都操作的是这个对象。 

public class ThreadLocalTest implements Runnable{

 ThreadLocal<Studen> studenThreadLocal = new ThreadLocal<Studen>();

 @Override

 public void run() {
 String currentThreadName = Thread.currentThread().getName();  System.out.println(currentThreadName + " is running...");

 Random random = new Random(); 

 int age = random.nextInt(100); 
 System.out.println(currentThreadName + " is set age: "  + age);
 Studen  studen = getStudent(); //通过这个方法,为每个线程都独立的 new 一个 student 对象,每个线程的的

student对象都可以设置不同的值 

 studen.setAge(age);
 System.out.println(currentThreadName + " is first get age: " + studen.getAge());  try {

 Thread.sleep(500); 

 } catch (InterruptedException e) {

 e.printStackTrace(); 

 }
 System.out.println( currentThreadName + " is second get age: " + studen.getAge());

 }

 private Studen getStudent() { 

 Studen studen = studenThreadLocal.get(); 

 if (null == studen) {

 studen = new Studen(); 

 studenThreadLocal.set(studen); 

 }

 return studen;

 }

 public static void main(String[] args) { 

 ThreadLocalTest t = new ThreadLocalTest();

 Thread t1 = new Thread(t,"Thread A"); 

 Thread t2 = new Thread(t,"Thread B"); 

 t1.start();

 t2.start();

 }

}

class Studen{

 int age;

 public int getAge() {

 return age;

 }

 public void setAge(int age) { 

 this.age = age;

 }

相关文章:

ThreadLocal的使用方式

1. ThreadLocal的使用方式 (1) 在关联数据类中创建private static ThreadLocal 在下面的类中&#xff0c;私有静态 ThreadLocal 实例&#xff08;serialNum&#xff09;为调用该类的静态 SerialNum.get() 方法的每个 线程维护了一个“序列号”&#xff0c;该方法将返回当前…...

全面理解:C++中的指针和迭代器,以及解引用操作符(*)和箭头操作符(->)的用法

指针与迭代器的基础概念 指针&#xff1a; 指针是一种变量&#xff0c;其值为另一种类型的对象在计算机内存中的地址。你可以使用指针来直接访问和操作它指向的对象。指针的使用非常强大&#xff0c;但也很危险&#xff0c;因为你有可能错误地操作内存&#xff0c;这可能会导致…...

Vite 使用学习指南

Vite 的基本概念和特点 Vite 是什么&#xff0c;它的主要特点是什么 Vite 是一个基于 ES modules 的前端构建工具&#xff0c;它的主要特点包括&#xff1a; 快速的冷启动&#xff1a;Vite 采用了基于浏览器原生 ES 模块的开发模式&#xff0c;可以在开发时快速启动应用&…...

【算法训练(day6)】双指针模板

一.双指针算法的由来和使用场景 通常情况下我们可能会遇到在某些可遍历的集合中寻找满足某种性质的字串或元素。这时候我们采取暴力的思路就会面临多重循环。我们可以利用题目中所给的集合并利用其性质将多重循环降成一重循环。光用语言描述可能不太好理解。接下来看几个双指针…...

免费常用的API接口大全

免费常用的API接口大全 OPEN AI &#xff1a; ChatGPT 能够模拟人类的语言行为&#xff0c;与用户进行自然的交互。ChatGPT 可以用于处理多种类型的对话&#xff0c;包括对话机器人、问答系统和客服机器人等。它还可以用于各种自然语言处理任务&#xff0c;比如文本摘要、情感分…...

【HTML】第 2 节 - HTML 标签

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、标题标签 3、段落标签 4、文本格式化标签 5、图像标签 5.1、基本作用 5.2、属性 6、超链接标签 7、音频标…...

MATLAB算法实战应用案例精讲-【数模应用】残差检验(附Java、python和MATLAB代码)

目录 几个高频面试题目 线性回归残差是否一定满足正态分布? 一般情况 特殊情况...

初学Qt(Day03)

今天概览 今天的目标是写一个动态的彩虹灯 一开始是有思路的。只是写的过程中有太多小bug了&#xff0c;真的是防不胜防 我的思路是&#xff1a; 主界面是一个开始界面&#xff0c;点击开始按钮之后&#xff0c;有一个子界面出现&#xff0c;显示出彩虹灯转动的效果。 内部的执…...

皮卡丘xss之htmlspecialchars、xss之href输出、xss之js输出

1.xss之htmlspecialchars htmlspecialchars()函数的功能如下&#xff1a; htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。 预定义的字符是&#xff1a; &#xff08;1&#xff09;& &#xff08;和号&#xff09;成为 &amp; &#xff08;2&#xff09;…...

ArrayList和LinkedList的区别

ArrayList和Vector使用了数组的实现&#xff0c;可以认为ArrayList或者Vector封装了对内部数组的操作&#xff0c;比如向数组中添加&#xff0c;删除&#xff0c;插入新的元素或者数据的扩展和重定向。 LinkedList使用了循环双向链表数据结构。与基于数组ArrayList相比&#xf…...

记录 vue3 webpack 使用 iframe 遇到的坑

需求 我尝试用Vue3写一个自己的主页&#xff0c;把常用的功能集中到主页中&#xff0c;如下图 后发现一个好玩的东西&#xff0c;js实现的在网页底部出现鱼和波浪&#xff0c;如下图&#xff0c;就像想也放到自己的主页中&#xff0c;搜索后发现可以在Vue中用iframe标签直接引…...

华为OD机试真题 Java 实现【去除多余空格】【2023Q1 100分】

一、题目描述 去除文本多余空格,但不去除配对单引号之间的多余空格。给出关键词的起始和结束下标,去除多余空格后刷新关键词的起始和结束下标。 条件约束: 不考虑关键词起始和结束位置为空格的场景;单词的的开始和结束下标保证涵盖一个完整的单词,即一个坐标对开始和结束…...

SAP-MM 条件类型字段解析

01、“定价类型”&#xff1a;定义此条件类型的代码和描述&#xff0c;代码不能重复&#xff0c;描述可更改&#xff0c;根据实际需要&#xff0c;条件类型可定制&#xff1b; 02、“存取顺序”&#xff1a;表示此条件类型在定价时&#xff0c;要到存取顺序号定义的条件表中读…...

C#,码海拾贝(28)——求解“对称正定方程组”的“平方根法”之C#源代码

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static partial class LEquations { /// <summary> /…...

碳纤维单丝外径测试中的纳米分辨率激光衍射法解决方案

摘要&#xff1a;碳纤维单丝热膨胀系数是碳纤维复合材料设计、生产与可靠性和寿命评估的重要参数&#xff0c;本文针对单丝径向高温热膨胀系数测试这一难题提出了相应的解决方案。解决方案的核心内容是基于激光衍射法和高温辐射加热&#xff0c;并采用衍射轮廓拟合技术以及相应…...

服务(第三十二篇)nginx做缓存服务器

nginx作为缓存服务配置语法 1、proxy_cache_path 配置语法&#xff08;即缓存路径配置语法&#xff09; Syntax&#xff1a;proxy_cache_path path [levelslevels] [use_temp_pathon|off] keys_zonename:size [inactivetime] [max_sizesize] [manager_filesnumber] [manager_s…...

Java 集合、数组、字符串的相互转换(关于list.toArray(new String[0])的源码分析)

在 Java 中&#xff0c;可以通过以下方式实现集合、数组和字符串之间的相互转换。 一、集合和数组的相互转化 ①、将集合转为数组&#xff1a;&#xff08;toArray 方法&#xff09; List<String> list new ArrayList<>(); list.add("apple"); lis…...

Redis的全局命令及相关误区

Redis中所说的数据结构是针对key-value中的value而言的。主要的结构包括String、哈希表、列表、集合等等在redis中存在16个库&#xff0c;涉及到后期的集群搭建只能使用0号库最为方便 查看所有键&#xff08;支持通配符&#xff09; keys * keys S*返回当前数据库中的键总数 …...

C++核心编程—类和对象,类的三大特性——封装、继承、多态

纵有疾风起&#xff0c;人生不言弃。本文篇幅较长&#xff0c;如有错误请不吝赐教&#xff0c;感谢支持。 &#x1f4ac;文章目录 一.类和对象的概念①什么是对象&#xff1f;②抽象和类1.类的基本概念2.类的声明与定义&#xff1a;3.对象的创建与使用 二.类的封装①为什么有封…...

keep-alive 是 Vue 内置的一个组件,被用来缓存组件实例。

文章目录 简介注意点使用 keep-alive 有以下优缺点优点缺点 简介 keep-alive 是 Vue 内置的一个组件&#xff0c;被用来缓存组件实例。 使用 keep-alive 包裹动态组件时&#xff0c;被包裹的组件实例将会被缓存起来&#xff0c;而不会被销毁&#xff0c;直到 keep-alive 组件…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目&#xff0c;核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容&#xff0c;附学习方向和应试技巧&#xff1a; 一、施工组织与进度管理 核心目标&#xff1a; 规…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)

注&#xff1a;文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件&#xff1a;STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...

李沐--动手学深度学习--GRU

1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...

AWS vs 阿里云:功能、服务与性能对比指南

在云计算领域&#xff0c;Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商&#xff0c;各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5]&#xff0c;我将从功能、服务和性能三个方面进行结构化对比分析&#…...

运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.

报错 找到package.json文件 找到这个修改成 "lint": "eslint --fix --ext .js,.vue src" 为elsint有配置结尾换行符&#xff0c;最后运行&#xff1a;npm run lint --fix...