Java 多线程之--ThreadLocal 简介

<span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">      在多线程开发中,经常会遇见在run方法里面调用一个公共的属性的事情,由于每次start都会创建一个线程,因此</span>
<span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">所</span><span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">有的线程共享一个属性,当其中任何一个线程更改了这个属性的值,这个属性在下面的使用过程中都会被改变,这</span>
<span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">回导</span><span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">致很多不期望发生的事情发生,这就叫做线程不安全的。先来一个例子说明这个问题。</span>
<span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">
</span>
package com.bird.concursey;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class UnsafeTask implements Runnable{

	private Date startDate;

	@Override
	public void run() {
		startDate = new Date();
		System.out.println("start thread " + Thread.currentThread().getId() + " " + startDate);
		try {
			TimeUnit.SECONDS.sleep((int)Math.rint(Math.random() * 10));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Thread finish " + Thread.currentThread().getId() + " " + startDate);
	}

	public static void main(String[] args) {
		UnsafeTask task = new UnsafeTask();
		for(int i = 0; i < 10; i++) {
			Thread thread = new Thread(task);
			thread.start();
			try {
				TimeUnit.SECONDS.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
	}
}

这里我们在主线程创建了十个分线程,然后每个线程都会实例化这个date,然后你会惊奇的发现,当所有的线程

运行完毕后,他们的结束时间都是一样的,运行结果如下。

start thread 8 Tue Sep 16 20:21:50 CST 2014
start thread 9 Tue Sep 16 20:21:52 CST 2014
start thread 10 Tue Sep 16 20:21:54 CST 2014
start thread 11 Tue Sep 16 20:21:56 CST 2014
start thread 12 Tue Sep 16 20:21:58 CST 2014
Thread finish 10 Tue Sep 16 20:21:58 CST 2014
Thread finish 11 Tue Sep 16 20:21:58 CST 2014
Thread finish 8 Tue Sep 16 20:21:58 CST 2014
start thread 13 Tue Sep 16 20:22:00 CST 2014
Thread finish 9 Tue Sep 16 20:22:00 CST 2014
start thread 14 Tue Sep 16 20:22:02 CST 2014
start thread 15 Tue Sep 16 20:22:04 CST 2014
Thread finish 14 Tue Sep 16 20:22:04 CST 2014
start thread 16 Tue Sep 16 20:22:06 CST 2014
Thread finish 12 Tue Sep 16 20:22:06 CST 2014
start thread 17 Tue Sep 16 20:22:08 CST 2014
Thread finish 16 Tue Sep 16 20:22:08 CST 2014
Thread finish 13 Tue Sep 16 20:22:08 CST 2014
Thread finish 15 Tue Sep 16 20:22:08 CST 2014
Thread finish 17 Tue Sep 16 20:22:08 CST 2014

主要因为所有的线程公用一个属性,有一个线程改变了他的值,导致后面的其实调用的都是一个变量的值,我们

的期望是每个Thread都有自己的属性的值,大家都是独立的,那该怎么做呢。

package com.bird.concursey;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class SafeTask implements Runnable {

	private static ThreadLocal<Date> startDate = new ThreadLocal<Date>() {
		protected Date initialValue() {
			return new Date();
		};
	};

	@Override
	public void run() {
		System.out.println("start thread " + Thread.currentThread().getId()
				+ " " + startDate.get());
		try {
			TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Thread finish " + Thread.currentThread().getId()
				+ " " + startDate.get());
	}

	public static void main(String[] args) {
		SafeTask task = new SafeTask();
		for (int i = 0; i < 10; i++) {
			Thread thread = new Thread(task);
			thread.start();
			try {
				TimeUnit.SECONDS.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
	}

}

这就是正确的代码,主要就是加入了ThreadLocal这个类,主要的目的就是这样就能保证每次线程开启的时候都

会去调用他的initvalue方法给这个属性付一个初值,然后每个线程都会自己维护这个值,各个线程之间都是独立的,

我们通过get方法就能获得对应的值,当然他也提供了set方法来更改他的值,或者remove等等,反正现在就是线程安

全的了。

时间: 2024-10-29 00:49:27

Java 多线程之--ThreadLocal 简介的相关文章

java多线程模式ThreadLocal原理简述及其使用详解

原创整理不易,转载请注明出处:java多线程模式ThreadLocal原理简述及其使用详解 代码下载地址:http://www.zuidaima.com/share/1781557457128448.htm ThreadLocal是为了使每个线程保存一份属于自己的数据. 先看一个使用ThreadLocal的实例. package com.zuidaima.aop.framework; import com.zuidaima.core.NamedThreadLocal; public abstra

java多线程学习-ThreadLocal

为了凑字,把oracle文档里介绍ThreadLocal抄过来 public class ThreadLocal<T> extends Object This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its ow

java 多线程(threadlocal)

package com.example; import java.util.Random; public class App { public static class MyRunnable1 implements Runnable { //ThreadLocal是一个线程局部变量 private ThreadLocal<String> threadlocal = new ThreadLocal<String>(); @Override public void run() { //

java 多线程 day06 threadLocal

import java.util.HashMap;import java.util.Map;import java.util.Random; /** * Created by chengtao on 17/12/3. * 继5 之后,ThreadLocal就是系统为我们提供的那个map */public class Thread0601_ThreadLocal { private static int data = 0; private static ThreadLocal<Integer>

java多线程--------深入分析 ThreadLocal 内存泄漏问题

前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能会导致内存泄漏.下面,我们将围绕三个方面来分析ThreadLocal 内存泄漏的问题 ThreadLocal 实现原理 ThreadLocal为什么会内存泄漏 ThreadLocal 最佳实践 ThreadLocal 实现原理 ThreadLocal的实现是这样的:每个Thread 维护一个 Thr

Java ThreadLocal 简介

ThreadLocal在Spring中发挥着重要的作用,在管理request作用域的Bean.事务管理.任务调度.AOP等模块都出现了它们的身影,起着举足轻重的作用.要想了解Spring事务管理的底层技术,ThreadLocal是必须攻克的山头堡垒. 我们知道spring通过各种模板类降低了开发者使用各种数据持久技术的难度.这些模板类都是线程安全的,也就是说,多个DAO可以复用同一个模板实例而不会发生冲突.我们使用模板类访问底层数据,根据持久化技术的不同,模板类需要绑定数据连接或会话的资源.但这

Java多线程与并发应用-(5)-如何优雅的使用ThreadLocal类

内容来自,张孝祥老师的张孝祥-Java多线程与并发库高级应用>视频教程 package com.lipeng; public class MyThreadLocalTest2 { private final static MyThreadLocal<String> myThreadLocal=new MyThreadLocal<String>(); /** * @param args */ public static void main(String[] args) { ne

java多线程18: ThreadLocal的作用

从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal.ThreadLocalMap里的是是线程自己要存储的对象,其他线程不需要去访问,也是访问不到的.各个线程中的ThreadLocal.ThreadLocalMap以及ThreadLocal.ThreadLocal中的值都是不同的对象. 至于为什么要使用ThreadLocal,不妨这么考虑这个问题.Ja

跟我学Java多线程——ThreadLocal

ThreadLocal是什么 ThreadLocal这个词如果直接翻译就是"本地线程",可是如果真的按"本地线程"来理解,那就确实大错特错了,ThreadLocal它并不是一个Thread,它跟Thread确实有关系,是用来维护Thread的有关变量的,把它命名为ThreadLocalVariable可能更容易让人理解,在多线程中ThreadLocal为变量在每个线程中都创建了一个跟特定线程有关的变量的副本,这样就可以使每个线程在运行中只可以使用与自己线程有关的特定