ThreadLocal-------线程范围内的数据共享

1、ThreadLocal的简介

        ThreadLocal,即线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构。这个结构被附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。
        可以通过set(T)方法来设置一个值,在当前线程下再通过get()方法获取到原先设置的值。

2、时间差的计算

      在下面的例子中,构建了一个常用的Profiler类,它具有begin()和end()两个方法,而end()方法返回从begin()方法调用开始到end()方法被调用时的时间差,单位是毫秒。

public class Profiler {

	private static ThreadLocal<Long> TIME_THREADLOCAL = new ThreadLocal<Long>();

	public static final void begin() {
		Long time = TIME_THREADLOCAL.get();
		if (time == null) {
			TIME_THREADLOCAL.set(System.currentTimeMillis());
		}
	}

	public static final long end() {
		return System.currentTimeMillis() - TIME_THREADLOCAL.get();
	}

}
    测试代码

public class Test {
	public static void main(String[] args) {
		Profiler.begin();
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Cost: " + Profiler.end() + " mills");
	}
}

3、线程范围内的数据共享,注意ThreadLocal的用法

// 线程内的共享数据,每次获取的实例都是和当前线程相关的  
class MyThreadScopeData {  
  
    public MyThreadScopeData() {  
    }  
  
    // 利用ThreadLocal存储和线程相关的ThreadScopeData.java的实例  
    private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();  
  
    // 用于获取ThreadScopeData.java和当前线程相关的实例  
    public static MyThreadScopeData getThreadInstance() {  
        MyThreadScopeData instance = map.get();  
        if (instance == null) {  
            instance = new MyThreadScopeData();  
            map.set(instance);  
        }  
        return instance;  
    }  
  
    private int age;  
    private String name;  
  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    @Override  
    public String toString() {  
        return "ThreadScopeData [age=" + age + ", name=" + name + "]";  
    }  
  
}  
       测试代码

public class ThreadScopeDataShare {  
  
    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();  
                    MyThreadScopeData myThreadScopeData = MyThreadScopeData  
                            .getThreadInstance();  
                    myThreadScopeData.setAge(data);  
                    myThreadScopeData.setName(data + "");  
                    System.out.println(Thread.currentThread().getName()  
                            + " has put data is "  
                            + myThreadScopeData.toString());  
                    // 模拟A模块使用数据  
                    new A().get();  
                    // 模拟B模块使用数据  
                    new B().get();  
                }  
            }).start();  
        }  
  
    }  
  
    // A模块  
    static class A {  
  
        public void get() {  
            MyThreadScopeData myThreadScopeData = MyThreadScopeData  
                    .getThreadInstance();  
            System.out.println("A from " + Thread.currentThread().getName()  
                    + " has put data is " + myThreadScopeData.toString());  
        }  
  
    }  
  
    // 模块  
    static class B {  
        public void get() {  
            MyThreadScopeData myThreadScopeData = MyThreadScopeData  
                    .getThreadInstance();  
            System.out.println("B from " + Thread.currentThread().getName()  
                    + " has put data is " + myThreadScopeData.toString());  
        }  
    }  
}  
      测试结果

Thread-0 has put data is ThreadScopeData [age=-1607661362, name=-1607661362]  
Thread-1 has put data is ThreadScopeData [age=-715028589, name=-715028589]  
A from Thread-0 has put data is ThreadScopeData [age=-1607661362, name=-1607661362]  
A from Thread-1 has put data is ThreadScopeData [age=-715028589, name=-715028589]  
B from Thread-0 has put data is ThreadScopeData [age=-1607661362, name=-1607661362]  
B from Thread-1 has put data is ThreadScopeData [age=-715028589, name=-715028589]  


4、利用ThreadLocal来保存之和当前线程有关的数据库连接

/** 
 * 数据库连接管理类 
 * @author 爽 
 * 
 */  
public class ConnectionManager {  
  
    /** 线程内共享Connection,ThreadLocal通常是全局的,支持泛型 */  
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();  
      
    public static Connection getCurrConnection() {  
        // 获取当前线程内共享的Connection  
        Connection conn = threadLocal.get();  
        try {  
            // 判断连接是否可用  
            if(conn == null || conn.isClosed()) {  
                // 创建新的Connection赋值给conn(略)  
                // 保存Connection  
                threadLocal.set(conn);  
            }  
        } catch (SQLException e) {  
            // 异常处理  
        }  
        return conn;  
    }  
      
    /** 
     * 关闭当前数据库连接 
     */  
    public static void close() {  
        // 获取当前线程内共享的Connection  
        Connection conn = threadLocal.get();  
        try {  
            // 判断是否已经关闭  
            if(conn != null && !conn.isClosed()) {  
                // 关闭资源  
                conn.close();  
                // 移除Connection  
                threadLocal.remove();  
                conn = null;  
            }  
        } catch (SQLException e) {  
            // 异常处理  
        }  
    }  
}  

 这样处理的好处:

  1. 统一管理Connection;
  2. 不需要显示传参Connection,代码更优雅;
  3. 降低耦合性。
5、模拟多线程的途径,使用FOR循环
// 模拟多线程的访问  
        for (int i = 0; i < 2; i++) {  
            new Thread(new Runnable() {  
                @Override  
                public void run() {  
                      
                }  
            }).start();  
        }  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值