`
wx1568520008
  • 浏览: 20408 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

java之自己做一个ThreadLocal

 
阅读更多

直接聊技术!

描述

ThreadLocal直译为 本地线程,但是实际意思却不是这样的,它是一个容器,用于存放本地线程的局部变量,到底为什么叫ThreadLocal,讲道理,我也不知道!


业务描述 在一个类中调用三个线程,三个线程分别进行报数1、2、3

 /**
 * [@author](https://my.oschina.net/arthor):稀饭
 * [@time](https://my.oschina.net/u/126678):下午8:10:59
 * @filename:Sequence.java
 */
package demo;

public interface Sequence {
	public int getNumber();
}
/**
 * [@author](https://my.oschina.net/arthor):稀饭
 * [@time](https://my.oschina.net/u/126678):下午8:12:24
 * @filename:ClientThread.java
 */
package demo;

public class ClientThread extends Thread {

	private Sequence sequence;

	public ClientThread(Sequence sequence) {
		// TODO Auto-generated constructor stub
		this.sequence = sequence;
	}

	/**
	 * @Title: run
	 * @Description: TODO
	 */
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName() + " ==> " + sequence.getNumber());
		}
	}
}
/**
 * @author:稀饭
 * @time:下午8:18:27
 * @filename:TestA.java
 */
package demo;

public class TestA implements Sequence {
	private static int number = 0;

	@Override
	public int getNumber() {
		// TODO Auto-generated method stub
		number = number + 1;
		return number;
	}

	public static void main(String[] args) {
		Sequence sequence = new TestA();
		ClientThread clientThread1 = new ClientThread(sequence);
		ClientThread clientThread2 = new ClientThread(sequence);
		ClientThread clientThread3 = new ClientThread(sequence);
		clientThread1.start();
		clientThread2.start();
		clientThread3.start();
	}
}

运行结果如下: Thread-0 ==> 1 Thread-2 ==> 3 Thread-1 ==> 2 Thread-2 ==> 5 Thread-0 ==> 4 Thread-2 ==> 7 Thread-1 ==> 6 Thread-0 ==> 8 Thread-1 ==> 9

**源码分析:**Thread没有按照先后顺序输出,这个可以理解,毕竟线程的启动是随机的,而为什么输出的结果不是1、2、3、1、2、3、1、2、3呢,仔细分析才发现,number是static的,是类所共享的,无法保证对不同线程来说是安全的,大家操作的都是同一个变量,当然一直在递增了。


那么如何做到各自线程递增这样的结果呢?


现在引入ThreadLocal,源码如下 /** * @author:稀饭 * @time:下午8:18:27 * @filename:TestA.java */ package demo;

public class TestB implements Sequence {
	private static ThreadLocal<Integer> container = new ThreadLocal<Integer>() {

		@Override
		protected Integer initialValue() {
			// TODO Auto-generated method stub
			return 0;
		}
	};

	@Override
	public int getNumber() {
		// TODO Auto-generated method stub
		container.set(container.get() + 1);
		return container.get();
	}

	public static void main(String[] args) {
		Sequence sequence = new TestB();
		ClientThread clientThread1 = new ClientThread(sequence);
		ClientThread clientThread2 = new ClientThread(sequence);
		ClientThread clientThread3 = new ClientThread(sequence);
		clientThread1.start();
		clientThread2.start();
		clientThread3.start();
	}
}

运行结果如下: Thread-0 ==> 1 Thread-1 ==> 1 Thread-2 ==> 1 Thread-1 ==> 2 Thread-0 ==> 2 Thread-1 ==> 3 Thread-2 ==> 2 Thread-0 ==> 3 Thread-2 ==> 3

源码解析:在TestA中引入ThreadLocal之后输出的结果变成了我上面说的那样,用了ThreadLocal之后每个线程独立了,虽然同样是static,但是线程独立了,也就是说ThreadLocal会为每一个不同的线程设置一个独立的副本。


现在才是最重要的地方,我们自己来实现一个ThreadLocal

先来分析一下ThreadLocal的api:

 public void set(T vlue) 将值放入线程局部变量中

 public T get() 从线程局部变量中获取

 public void remove() 从线程局部中移除值

 protected T initialValue() 返回线程局部变量中的初始值

以下是我自己实现的ThreadLocal


/**
 * @author:稀饭
 * @time:上午10:36:34
 * @filename:ThreadLocalContainer.java
 */
package demo;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class ThreadLocalContainer<T> {

	private T value;
	//这里使用了同步Map
	private Map<String, T> map = Collections.synchronizedMap(new HashMap<String, T>());

	// 将值放入线程局部变量中
	public void set(T vlue) {
		map.put(Thread.currentThread().getName(), vlue);
	}

	// 从线程局部变量中获取
	public T get() {
		if (!map.containsKey(Thread.currentThread().getName())&&map.get(Thread.currentThread().getName()) == null) {
			value = initialValue();
			map.put(Thread.currentThread().getName(), value);
		}
		T v = map.get(Thread.currentThread().getName());
		return v;
	}

	// 从线程局部中移除值
	public void remove() {
		if (map.containsKey(Thread.currentThread().getName())) {
			map.remove(Thread.currentThread().getName());
		}
	}

	// 返回线程局部变量中的初始值
	protected T initialValue() {
		return value;
	}
}

**源码分析:**在源码中我使用了线程安全的Map也就是同步Map,目的是为了防止出现多线程出现的不安全问题。


**Note:发布的这些文章全都是自己边学边总结的,难免有纰漏,如果发现有不足的地方,希望可以指出来,一起学习咯,么么哒。 开源爱好者,相信开源的力量必将改变世界: **  osc    : https://git.oschina.net/xi_fan github: https://github.com/wiatingpub

转载于:https://my.oschina.net/u/2286602/blog/833941

分享到:
评论

相关推荐

    java中ThreadLocal详解

    在Java多线程编程中,`ThreadLocal`是一个非常重要的工具类,它提供了一种在每个线程内部存储线程私有实例的方法。通常情况下,当多个线程共享某个变量时,可能会引发线程安全问题。而`ThreadLocal`则提供了另一种...

    java事务 - threadlocal

    当Java事务与ThreadLocal结合使用时,可以在不同的线程中维护各自的事务状态,比如在Spring框架中,每个线程的ThreadLocal可以存储一个TransactionStatus对象,这样就可以在线程内部管理当前事务的状态,而不会影响...

    java 简单的ThreadLocal示例

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...

    Java中ThreadLocal的设计与使用

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,用于为每个线程提供独立的变量副本。理解ThreadLocal的工作原理和使用方法对于编写高效、安全的多线程程序至关重要。 ### ...

    java中ThreadLocal类的使用

    Java中的`ThreadLocal`类是一个非常实用的工具,它提供了线程局部变量的功能。线程局部变量意味着每个线程都拥有自己独立的变量副本,互不干扰,这在多线程编程中尤其有用,可以避免数据共享带来的同步问题。下面...

    Java多线程 之 临界区、ThreadLocal.docx

    在这个例子中,`ThreadLocalTest`类中的`threadLocal`变量为每个线程初始化一个随机值,并且`increament()`方法会增加当前线程的`ThreadLocal`变量的值。由于每个线程都有自己的副本,因此不会发生数据竞争。 总结...

    Java ThreadLocal详解_动力节点Java学院整理

    从本质上说,ThreadLocal是一种存储机制,它可以在每个线程中存储一个变量的副本,这样每个线程都可以访问自己的变量副本,而不需要与其他线程共享同一个变量。这种机制可以解决多线程编程中的线程安全问题,并且...

    ThreadLocal应用示例及理解

    **线程局部变量(ThreadLocal)是Java编程中一个非常重要的工具类,它在多线程环境下提供了线程安全的数据存储。ThreadLocal并不是一个变量,而是一个类,它为每个线程都创建了一个独立的变量副本,使得每个线程都...

    Java并发编程学习之ThreadLocal源码详析

    ThreadLocal的实现原理可以总结为:每个线程都有一个自己的ThreadLocalMap,用于存放线程的本地变量;ThreadLocal的set、get、remove方法都是基于ThreadLocalMap的操作。 ThreadLocal的优点是可以解决多线程访问...

    Java资料-详解ThreadLocal

    `ThreadLocal`在Java中是一个非常重要的工具类,它为每个线程提供了单独的变量副本,每个线程都可以独立地改变自己副本的值,而不会影响其他线程所对应的副本。`ThreadLocal`的全称是`java.lang.ThreadLocal`,它并...

    JAVA ThreadLocal类深入

    ThreadLocal并不是一个线程对象,而是线程局部变量,即threadlocalvariable,它的主要作用是确保每个线程都有自己的变量实例,互不干扰。 ### 一、ThreadLocal工作原理 ThreadLocal通过内部的Map存储每个线程的...

    java ThreadLocal多线程专属的变量源码

    java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多...

    ThreadLocal

    ThreadLocal是一个非常重要的Java并发工具类,它的核心概念在于为每一个线程提供了一个独立的变量副本,从而避免了线程之间的数据竞争问题。这使得每个线程在访问ThreadLocal变量时,实际上是在访问该变量的一个独立...

    深入理解 Java 之 ThreadLocal 工作原理1

    ThreadLocal是Java中用于线程局部变量的一个工具类,它的工作原理主要体现在如何在不同的线程之间隔离变量的副本,确保每个线程拥有自己的独立数据。这个设计模式在多线程编程中尤其有用,因为它避免了传统的同步...

    使用Java ThreadLocal.docx

    Java中的ThreadLocal是一个非常有用的工具类,它提供了一种线程局部变量的机制。线程局部变量(ThreadLocal)的特点是每个线程都有其独立的副本,这些副本之间互不干扰,即使它们共享同一个ThreadLocal实例。这使得...

    ThreadLocal的几种误区

    误区一:ThreadLocal是Java线程的一个实现 ThreadLocal并非Java线程的实现,它只是一个工具类,用于创建线程局部变量。ThreadLocal并不直接管理线程,而是为每个线程创建一个单独的变量副本。当线程使用ThreadLocal...

    Java并发编实践之ThreadLocal变量.doc

    Java并发编程实践中,ThreadLocal变量是一个非常重要的工具,它在JDK1.2版本就已经引入。ThreadLocal不是代表一个线程实例,而是一种线程局部变量的机制,它为每个线程提供了一个独立的变量副本,各个线程可以独立地...

    JAVA并发-自问自答学ThreadLocal.pdf

    【ThreadLocal】是Java编程语言中用于处理线程局部变量的一个工具类,它提供了一种在多线程环境中实现线程安全的局部变量的方式。在Java的并发编程中,ThreadLocal是一个非常重要的概念,它可以帮助我们创建独立于...

    简单分析Java线程编程中ThreadLocal类的使用共

    Java线程编程中的ThreadLocal类是一个非常重要的工具,它在多线程环境下提供了一种线程局部变量的机制。ThreadLocal并非是简单的变量,而是一种能够确保每个线程都拥有独立副本的变量容器。理解ThreadLocal的工作...

Global site tag (gtag.js) - Google Analytics