关闭

java回忆录(3)—ThreadLocal解决线程资源共享问题

标签: 线程线程安全ThreadLocal
188人阅读 评论(0) 收藏 举报
分类:

ThreadLocal 本地线程,可以解决线程之前静态资源共享的问题,做到线程安全

直接上代码

定义一个接口

package org.blueskytoolkit.source.thread.threadlocal;
/**
 * 序列化接口
 * @author zw
 * 2016年6月1日上午9:38:32
 */
public interface Sequence {
	public int getNumber();
}
一个线程类 这里是继承的方式
package org.blueskytoolkit.source.thread.threadlocal;

public class ThreadDome extends Thread{

	private Sequence sequence;
	public ThreadDome(Sequence sequence) {
		this.sequence = sequence;
	}
	@Override
	public void run() {
		for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + " => " + sequence.getNumber());
        }
	}
}
把每个线程打印3次看看数据增长值

使用ThreadLocal类

package org.blueskytoolkit.source.thread.threadlocal;

public class ThreadDomeTest2 implements Sequence {
	
	/**
	 * 每个线程相互独立了,同样是 static 变量,对于不同的线程而言,它没有被共享,
	 * 而是每个线程各一份,这样也就保证了线程安全。 也就是说,TheadLocal 为每一个线程提供了一个独立的副本
	 * 
	 * 通过 ThreadLocal 封装了一个 Integer 类型的 numberContainer 静态成员变量,并且初始值是0。
	 * 再看 getNumber() 方法,首先从 numberContainer 中 get 出当前的值,加1,随后 set 到 numberContainer 中,最后将 numberContainer 中 get 出当前的值并返回
	 */
	
	 private static ThreadLocal<Integer> numberContainer = new ThreadLocal<Integer>() {
	        @Override
	        protected Integer initialValue() {
	            return 0;
	        }
	    };

	    public int getNumber() {
	        numberContainer.set(numberContainer.get() + 1);
	        return numberContainer.get();
	    }

	    /**
	     * public void set(T value):将值放入线程局部变量中
	     * public T get():从线程局部变量中获取值
	     * public void remove():从线程局部变量中移除值(有助于 JVM 垃圾回收)
	     * protected T initialValue():返回线程局部变量中的初始值(默认为 null) 
	     * @param args
	     */
	    public static void main(String[] args) {
	        Sequence sequence = new ThreadDomeTest2();
	        ThreadDome thread1 = new ThreadDome(sequence);
	        ThreadDome thread2 = new ThreadDome(sequence);
	        ThreadDome thread3 = new ThreadDome(sequence);

	        thread1.start();
	        thread2.start();
	        thread3.start();
	    }
}
输出结果,每个线程是单独的资源  数值不会随着其他线程而变化

这里自定义一个ThreadLocal类 实现主要的几个api即可

package org.blueskytoolkit.source.thread.threadlocal;

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

/**
 * 自定义一个threadlocal
 * 一个类中使用了 static 成员变量的时候,一定要多问问自己,这个 static 成员变量需要考虑“线程安全”吗?(也就是说,多个线程需要独享自己的 static 成员变量
 * @author zw
 * 2016年6月1日上午10:25:45
 * @param <T>
 */
public class MyThreadLocal<T> {

	/**
	 * 返回了一个线程安全的实现了 Map 接口的 实现类 HashMap 支持多线程数据的同步。保证多线程访问数据的一致性
	 */
	private Map<Thread, T> map = Collections
			.synchronizedMap(new HashMap<Thread, T>());

	public void set(T value) {
		map.put(Thread.currentThread(), value);
	}
	//获取
	public T get() {
        Thread thread = Thread.currentThread();
        T value = map.get(thread);
        if (value == null && !map.containsKey(thread)) {
        	//拿到默认值
            value = initialValue();
            map.put(thread, value);
        }
        return value;
    }
	//	移除
    public void remove() {
        map.remove(Thread.currentThread());
    }
    //初始化
    protected T initialValue() {
        return null;
    }
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:112721次
    • 积分:2049
    • 等级:
    • 排名:第18730名
    • 原创:93篇
    • 转载:37篇
    • 译文:0篇
    • 评论:29条
    最新评论