ThreadLocal类及使用技巧

Java线程是一项非常基本和重要的技术,在偏底层和偏技术的Java程序中不可避免地要使用到Java多线程技术,那么数据的共享也就是我们必须考虑的问题之一,自然我也就会想到ThreadLocal和synchronized。

ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题。ThreadLocal为每个线程中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果虽然耗费一些内存,但可以大大降低线程同步所带来性能消耗,同时也减少了线程并发控制的复杂度。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。二者虽然都是解决多线程并发访问的问题,但是区别很大。Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。下面是一个小例子,使用ThreadLocal时我们可以参照一下它的写法:

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class ThreadLocalTest {

	private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
	private static ThreadLocal<MyThreadScopeData> myThreadScopeData = new ThreadLocal<MyThreadScopeData>();
	public static void main(String[] args) {
		for(int i=0;i<2;i++){
			new Thread(new Runnable(){
				@Override
				public void run() {
					int data = new Random().nextInt();
					System.out.println(Thread.currentThread().getName()
							+ " has put data :" + data);
					x.set(data);
					MyThreadScopeData.getThreadInstance().setName("name" + data);
					MyThreadScopeData.getThreadInstance().setAge(data);
					new A().get();
					new B().get();
				}
			}).start();
		}
	}

	static class A{
		public void get(){
			int data = x.get();
			System.out.println("A from " + Thread.currentThread().getName()
					+ " get data :" + data);
			MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
			System.out.println("A from " + Thread.currentThread().getName()
					+ " getMyData: " + myData.getName() + "," +
					myData.getAge());
		}
	}

	static class B{
		public void get(){
			int data = x.get();
			System.out.println("B from " + Thread.currentThread().getName()
					+ " get data :" + data);
			MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();
			System.out.println("B from " + Thread.currentThread().getName()
					+ " getMyData: " + myData.getName() + "," +
					myData.getAge());
		}
	}
}

class MyThreadScopeData{

	private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();

	private String name;
	private int age;

	private MyThreadScopeData(){}
	public static /*synchronized*/ MyThreadScopeData getThreadInstance(){
		MyThreadScopeData instance = map.get();
		if(instance == null){
			instance = new MyThreadScopeData();
			map.set(instance);
		}
		return instance;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

总结:synchronized是利用锁的机制使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal却为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized正好相反,它用于在多个线程间通信时能够获得数据共享。具体使用什么我们要看编程时的应用环境而定。

时间: 2024-11-05 02:57:46

ThreadLocal类及使用技巧的相关文章

6.ThreadLocal类及应用技巧

1 import java.util.Random; 2 3 /** 4 * ThreadLocal类及应用技巧 5 * ******************************************************************* 6 * 每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map中增加一条记录,key 7 * 分别是各自的线程,values是各自的set方法穿进去的值.在线程结束时可以调用ThreadLocal.clear();

多线程06_张孝祥-ThreadLocal类及应用技巧

使用ThreadLocal类实现线程范围内的共享数据: 确保每个线程都有自己私有的变量和取到自己的变量.下面用ThreadLocal类实现,替代上节课中的map用法 代码: package org.yla.thread; import java.util.Random; /** * 使用ThreadLocal类实现线程范围内的私有数据 * 替代上节课map的作用 * @author huo_chai_gun * 2014年12月18日下午3:25:35 */ public class Threa

如何实现线程范围内共享数据 -- ThreadLocall类及其应用技巧

目标:如何保证各自线程上的数据是独立的,即A线程上数据只能被A线程操作 1:示例线程共享变量 我们先来看一个反例 package com.prepare.study; import java.util.Random; /** * @author: yinlm * @Date: Created in 2018/4/18 * @Description:多个线程数据混乱的示例 */ public class ThreadTest2 { // static 修饰 表示这是个全局变量 private st

【ThreadLocal】深入JDK源码之ThreadLocal类

学习JDK中的类,首先看下JDK API对此类的描述,描述如下: 该类提供了线程局部 (thread-local) 变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本.ThreadLocal其实就是一个工具类,用来操作线程局部变量,ThreadLocal 实例通常是类中的 private static 字段.它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联. 例如,以下类生成对每个线程

弄明白ThreadLocal类

1.ThreadLocal类的由来 因为有问题,人类就会想法设法的创造一些东西出来解决问题,嗯,这句话同意吧. 假如目前有这么一个问题:有个家庭,三个孩子都想看妈妈买的一本童话书,但是只有一本书,该如何是好? 方法一:家里没钱买第二本了,那就排队看,谁跑得快来到妈妈面前的就先看.后面来晚的,候着等着.等前面的看完再到你.于是 以时间换空间的synchronized 类出现了. 方法二:多大的事儿,你们爸爸有钱,随便任性.立马再买两本一模一样的,人手一本.于是以空间换时间的ThreadLocal类

ThreadLocal类详解

众所周知,ThreadLocal对象可以每一个线程保存一份值,可以避免因线程间共享数据带来的问题. 其实现的原理,大致如下,具体的可以参考JDK里的源码. Thread类中,有一个threadLocals字段,它是ThreadLocalMap类型(ThreadLocal里的一个静态内部类).该字段存放当前线程下,所有与ThreadLocal相关的值.该对象是一个Map,key为ThreadLocal对象,value为所存放的值. 在ThreadLocal类里,有两个重要的方法:set()和get

用ThreadLocal类实现线程安全的正确姿势

大家通常知道,ThreadLocal类可以帮助我们实现线程的安全性,这个类能使线程中的某个值与保存值的对象关联起来.ThreadLocal提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回由当前执行线程在调用set时设置的最新值.从概念上看,我们把ThreadLocal<T>理解成一个包含了Map<Thread,T>的对象,其中Map的key用来标识不同的线程,而Map的value存放了特定该线程的某个值.但是ThreadL

ThreadLocal类的实现用法

ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名为ThreadLocalVar更加合适.线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突. 从线程的角度看,每个线程都保持一个对其线程局部变量副本

2015年11月26日 Java基础系列(三)ThreadLocal类初级学习

序,ThreadLocal类是为了解决多线程的安全问题.线程安全的意思也就是说每个线程操作自己的变量,不要对其他线程的值造成影响. 在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性. 1 ThreadLocal解决多线程安全问题的思路是通过ThreadLocalMap进行管控,就像一个Map中存在多个键值对,ThreadLocalMap可以对比Map进行理解. 2 一般通过覆盖ThreadLocal的init