Java 中ThreadLocal类详解
作者:赵杰A-124 发布时间:2022-01-31 19:58:17
标签:Java,ThreadLocal
ThreadLocal类,代表一个线程局部变量,通过把数据放在ThreadLocal中,可以让每个线程创建一个该变量的副本。也可以看成是线程同步的另一种方式吧,通过为每个线程创建一个变量的线程本地副本,从而避免并发线程同时读写同一个变量资源时的冲突。
示例如下:
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.sun.javafx.webkit.Accessor;
public class ThreadLocalTest {
static class ThreadLocalVariableHolder {
private static ThreadLocal<Integer> value = new ThreadLocal<Integer>() {
private Random random = new Random();
protected synchronized Integer initialValue() {
return random.nextInt(10000);
}
};
public static void increment() {
value.set(value.get() + 1);
}
public static int get() {
return value.get();
}
}
static class Accessor implements Runnable{
private final int id;
public Accessor(int id) {
this.id = id;
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
ThreadLocalVariableHolder.increment();
System.out.println(this);
Thread.yield();
}
}
@Override
public String toString() {
return "#" + id + ": " + ThreadLocalVariableHolder.get();
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new Accessor(i));
}
try {
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.shutdownNow();
}
}
运行结果:
#1: 9685
#1: 9686
#2: 138
#2: 139
#2: 140
#2: 141
#0: 5255
。。。
由运行结果可知,各线程都用于各自的Local变量,并各自读写互不干扰。
ThreadLocal共提供了三个方法来操作,set,get和remove。
在Android 中的Looper,即使用了ThreadLocal来为每个线程都创建各自独立的Looper对象。
public final class Looper {
private static final String TAG = "Looper";
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
。。。
}
当某个线程需要自己的Looper及消息队列时,就调用Looper.prepare(),它会为线程创建属于线程的Looper对象及MessageQueue,并将Looper对象保存在ThreadLocal中。
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 1. 栈1.1 概念栈:是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。特点:栈中的数据元素遵循先进后出的原则,但要注意进的
- 在分布式系统中,配置文件散落在每个项目中,难于集中管理,抑或修改了配置需要重启才能生效。下面我们使用 Spring Cloud Config
- Synchronized的用法在多线程并发问题中,常用Synchronized锁解决问题。Synchronized锁通常用于同步示例方法,同
- 相信对于打印三角形都没什么难度,只需要利用for循环嵌套使用就行但是对于打印圆形和三角形不同因为到圆心距离相等的点一般不会横坐标和纵坐标都为
- 很多核心 Java 面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework),理解核心线
- 1 spring-retry是什么?以往我们在进行网络请求的时候,需要考虑网络异常的情况,本文就介绍了利用spring-retry,是spr
- @Cacheable在同一类中方法调用无效上述图片中,同一个类中genLiveBullets()方法调用同类中的queryLiveByRoo
- 当游戏在手机/模拟器上卡死,logcat没有日志输出,也没有卡死堆栈信息或者bugly也没有捕获到异常,你是否很焦急?本文介绍一下我们项目中
- 问题描述 在某一天打开电脑后,idea里的代码无缘无故地就爆红了,不但spring框架爆红,就
- MyBatis 通过包含的jdbcType类型BIT FLOAT CHAR &nbs
- 1.根据单个分隔字符用split截取例如string st="GT123_1";string[] sArray=st.s
- RocketMQ存储路径默认是${ROCKRTMQ_HOME}/store,主要存储消息、主题对应的消息队列的索引等。1、概述查看其目录文件
- 实例如下:package com.bwsk.modules.weixin.util;import java.util.Random;/**
- 写在前面在前后端交互过程中,为了保证信息安全,我们往往需要加点用户验证。本文介绍了用springboot简单整合token。springbo
- 本文实例讲述了Java实现求解一元n次多项式的方法。分享给大家供大家参考,具体如下:项目需要做趋势预测,采用线性拟合、2阶曲线拟合和指数拟合
- MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移
- 本文实例讲述了Java基于Tcp的基础聊天功能。分享给大家供大家参考,具体如下:最基础的聊天,用户端和服务器端每次说一句,而且严格规定了先后
- 通常来说,多线程的并发及条件断点的debug是很难完成的,或许本篇文章会给你提供一个友好的调试方法。让你在多线程开发过程中的调试更加的有的放
- MD5,全称为 Message Digest Algorithm 5(消息摘要算法第五版).详情请参考 * :MD5MD5加密后是一个字
- /// <summary> /// 遍历Co