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中。


猜你喜欢
- 本文实例讲述了Java使用TCP套接字实现多人聊天功能。分享给大家供大家参考,具体如下:废话不多说,直接开搞:先创建一个服务端:packag
- public static string encode(string str) { &
- 本文实例讲述了Winform中Treeview实现按需加载的方法,非常具有实用价值。分享给大家供大家参考。具体分析如下:最近项目里用到tre
- 这篇文章主要介绍了Java继承方法重写实现原理及解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友
- 本文实例讲述了java编程实现基于UDP协议传输数据的方法。分享给大家供大家参考,具体如下:UDP协议(User Datagram Prot
- 一、建立一个maven工程 pom类型统一管理依赖以及版本号子工程不会使用所有的定义的依赖子工程使用依赖时无需指定版本号其pom.xml&l
- 首先来说一下本文中例子所要实现的功能:基于ProtoBuf序列化对象使用Socket实现时时通信数据包的编码和解码下面来看具体的步骤:一、U
- 本文实例讲述了C#实现为一张大尺寸图片创建缩略图的方法。分享给大家供大家参考。具体实现方法如下:public static Bitmap C
- 准备工作这里就不说了,包括签约和申请APPID,附上微信开放平台APP开发步骤,不懂的同学可以参考这里:https://pay.weixin
- 前言哈喽,我是小黑, 最近学了java的输入输出流后一直心痒痒,总想找一点事情来做,所以用java代码来实现了一下统计代码的所有行数,看一下
- using System;using System.Data;using System.Data.OleDb;namespace ZFSof
- 优点1.观察者和被观察者是抽象耦合的。2.建立一套触发机制。缺点1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知
- 一、创建字符串创建字符串的方式有三种:// 方式一String str = "Hello Bit";// 方式二Stri
- 前言继承是面向对象语法的三大特征之一。继承可以降低代码编写的冗余度,提高编程的效率。通过继承,子类获得了父类的成员变量和方法。一个子类如何继
- StringBuilder与StringBuffer是两个常用的操作字符串的类。大家都知道,StringBuilder是线程不安全的,而St
- 死锁问题死锁定义多线程编程中,因为抢占资源造成了线程无限等待的情况,此情况称为死锁。死锁举例注意:线程和锁的关系是:一个线程可以拥有多把锁,
- 为了是java中的对象便于理解,我们可以使用一款比较好用的数据格式,在数据解析的时候也会经常用到,它就是JSON。在这里我们转换对象和字符串
- 本文实例讲述了C#实现在Form里面内嵌dos窗体的方法。分享给大家供大家参考。具体如下:using System;using System
- 本文实例讲述了C#实现带百分比的进度条功能。分享给大家供大家参考,具体如下:功能需求:如果程序中会执行一个耗时的计算过程,我想在用户点击按钮
- 目录绘制流程Measure 测量流程MeasureSpeclayout 布局流程draw 绘制流程相关类 & 概念DecorView