首页 > 其他分享 >Thread类中的threadLocals

Thread类中的threadLocals

时间:2023-07-21 17:05:58浏览次数:43  
标签:thread Thread -- ThreadLocal 线程 sn threadLocals 类中


ThreadLocal在1.6版本中不是用一个全局的Map来存各个线程的变量副本,而是在Thread类中有一个ThreadLocalMap的变量,然后用Thread.currentThread().threadLocals.get(this)来引用的各线程变量副本,这样避免了去同步全局的Map

 

ThreadLocal使用的简单例子:

 

 

package com.test;

public class TestNum {
	// ①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
	private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {
		public Integer initialValue() {
			return 0;
		}
	};

	// ②获取下一个序列值
	public int getNextNum() {
		seqNum.set(seqNum.get() + 1);
		return seqNum.get();
	}

	public static void main(String[] args) {
		TestNum sn = new TestNum();
		// ③ 3个线程共享sn,各自产生序列号
		TestClient t1 = new TestClient(sn);
		TestClient t2 = new TestClient(sn);
		TestClient t3 = new TestClient(sn);
		t1.start();
		t2.start();
		t3.start();
	}

	private static class TestClient extends Thread {
		private TestNum sn;

		public TestClient(TestNum sn) {
			this.sn = sn;
		}

		public void run() {
			for (int i = 0; i < 3; i++) {
				// ④每个线程打出3个序列值
				System.out.println("thread[" + Thread.currentThread().getName() + "] --> sn["
						 + sn.getNextNum() + "]");
			}
		}
	}
}

 

 通常我们通过匿名内部类的方式定义ThreadLocal的子类,提供初始的变量值,如例子中①处所示。TestClient线程产生一组序列号,在③处,我们生成3个TestClient,它们共享同一个TestNum实例。运行以上代码,在控制台上输出以下的结果:

 

thread[Thread-0] --> sn[1]


thread[Thread-1] --> sn[1]


thread[Thread-2] --> sn[1]


thread[Thread-1] --> sn[2]


thread[Thread-0] --> sn[2]


thread[Thread-1] --> sn[3]


thread[Thread-2] --> sn[2]


thread[Thread-0] --> sn[3]


thread[Thread-2] --> sn[3]


 

考察输出的结果信息,我们发现每个线程所产生的序号虽然都共享同一个TestNum实例,但它们并没有发生相互干扰的情况,而是各自产生独立的序列号,这是因为我们通过ThreadLocal为每一个线程提供了单独的副本。

 

 

上面例子中,是在自己的类中定义ThreadLocal,那么,那么,可否直接使用Thread.currentThread().threadLocals?

 

不可以的,因为threadLocals变量在Thread中时package的访问权限,只能在同一个包下访问。

 

但是可以通过反射来得到threadLocals中的内容,参考:

 

http://stackoverflow.com/questions/2001353/java-list-thread-locals

 

 

threadLocals 是干什么用的?

 

是线程存放多个ThreadLocal实例的。

 

 

 

ThreadLocal首先通过当前线程t得到threadLocals,然后把自身this作为key,从threadLocals中得到存储在线程本地的相关的数据

 

ThreadLocal中get 和set方法如下:

 

 

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

 

 

 

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

    

    

    其中 getMap方法简单如下:

    

 

ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

 

 

 

总结ThreadLocal原理:ThreadLocal对象相当于线程私有财产(数据)的经纪人,为线程的私有财产(数据)提供存储和获取的功能

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:thread,Thread,--,ThreadLocal,线程,sn,threadLocals,类中
From: https://blog.51cto.com/u_16200746/6803331

相关文章

  • python同一个类中的函数如何相互调用
    Python同一个类中的函数如何相互调用在Python中,一个类中的函数可以相互调用,这可以帮助我们更好地组织和管理代码。在这篇文章中,我们将介绍如何在同一个类中的函数之间进行相互调用,并以一个具体的问题为例进行说明。问题描述假设我们正在开发一个学生管理系统,我们需要实现以下功......
  • MIT 6.S081 Thread switching
    Multiplexingxv6通过将cpu从一个进程切换到另一个进程来实现multiplex(多路复用),进程的切换会在两种情形下发生:xv6的sleep与wakeup机制在进程等待IO完成或者等待子进程退出又或者在sleep系统调用中等待的时候切换进程。xv6会周期性地强制切换进程,从而应对那些长时......
  • Java详解ThreadLocal
    threadlocal1基础现象:threadlocal作为一个全局变量,在不同的线程去get的时候能够获取不同的值。应用场景:SimpleDateFormat线程不安全,每个线程都要用,new太多,放到threadlocal中线程池可反复使用。一个请求链路很长,经过数个服务,每次都要放到参数带着。改为直接放到threadlocal作为上下......
  • python threadpool
    Python线程池详解在并发编程中,线程池是一种常见的设计模式,它可以提高程序的性能和响应能力。Python中有许多库可以实现线程池,其中最常用的是concurrent.futures模块中的ThreadPoolExecutor类。本文将介绍Python线程池的工作原理、使用方法和一些示例代码。什么是线程池?线程池是......
  • 类中的vector初始化
    (21条消息)vector在类中声明问题_c++应输入类型说明符_线上幽灵的博客-CSDN博客在类中,vector不可以直接用下面的方式初始化 这应该是因为编译器无法知道这是函数还是vector定义,可以通过base(){a.resize(10)}或者base():a(10,1){}这种方式再初始化......
  • ThreadPoolExecutor线程池用法简介
    ThreadPoolExecutor 是Java中用于管理线程池的类,它提供了一种方便的方式来执行多线程任务。通过使用线程池,我们可以有效地管理和复用线程,提高程序的性能和资源利用率。下面是 ThreadPoolExecutor 线程池的详细用法介绍:创建线程池对象:ThreadPoolExecutorexecutor=ne......
  • Cobalt Strike进程注入——CreateRemoteThread案例复现和检测
    CobaltStrike进程注入——CreateRemoteThread案例复现和检测内网两台机器,操作如下: 我使用的是powershell反弹shell执行:看到的sysmon数据采集Networkconnectiondetected:RuleName:Alert,MetasploitUtcTime:2023-07-1803:00:37.856ProcessGuid:{d4c3f587-331d-64......
  • 开放原子训练营(第二季)RT-Thread Nano学习营刘玉宽
         4月22日周六,早早起床充满期待的来到了北京艾丽华酒店,参加“2023年RT-Thread线下培训”。这是疫情三年以来开放原子在北京第一次组织的线下活动。    进入到会场,被震撼了,好火爆啊————满满一屋子人,有白发苍苍的老者、有职场专家、有在校大学生、还有年仅6岁......
  • 十八、QThread线程
    1.进程线程关系介绍一个应用程序至少要有一个进程QProcess类可以开新的进程一个进程至少会有一个线程QThread2.使用方法(1)创建类实现QThread类或者QObject类(2)重写父类的run方法,在run方法中写入线程要做的事,只有run方法在线程中(3)创建对象,调用start方法,开启线程(4)termi......
  • ThreadPoolTaskExecutor自定义线程池的配置和使用
    ThreadPoolTaskExecutor自定义线程池的配置和使用线程池ThreadPoolTaskExecutor和ThreadPoolExecutor的区别ThreadPoolExecutor,这个类是JDK中的线程池类,继承自Executor,里面有一个execute()方法,用来执行线程,线程池主要提供一个线程队列,队列中保存着所有等待状态的线程,避免了创......