java的local_Java TheadLocal 和 实现

多线程场景下需要注意线程安全. 一种方法是给竞争资源上锁, 该资源在某个时刻仅能被某一个线程占用; 另一种方法就是大家都使用各自的资源, 不要相互干扰, 我们可以借助 TheadLocal 来实现.

模拟场景: 我们要做一个ID生成器, 要求多线程使用的时候, 每个线程可以独立工作生成自增的ID.

/**

* ID 生成器

*/

public class IdGenerator {

private static ThreadLocal id = new ThreadLocal() {

@Override

protected Long initialValue() {

return 0L;

}

};

/**

* 获得一个新的 ID

* @return

*/

public Long getNumber() {

id.set(id.get() + 1);

return id.get();

}

}

/**

* 独立任务, 要求在任务内获取从1开始的自增ID

*/

class Task implements Runnable {

private IdGenerator idGenerator;

public Task(IdGenerator idGenerator) {

this.idGenerator = idGenerator;

}

@Override

public void run() {

for (int i = 0; i < 5; i++) {

System.out.println(Thread.currentThread().getName() + ":" + idGenerator.getNumber());

}

}

}

调用:

public class Main {

public static void main(String[] args) {

IdGenerator idGenerator = new IdGenerator();

Thread[] threads = new Thread[3];

for (int i = 0; i < threads.length; i++) {

Task task = new Task(idGenerator);

threads[i] = new Thread(task);

}

for (int i = 0; i < threads.length; i++) {

threads[i].start();

}

}

}

实现 ThreadLocal

从以上例子看出, ThreadLocal 的核心就是让每个线程使用独立的(隔离的)资源, 我们可以用 Hash 来模拟这个过程:

public class DiyThreadLocal {

private Map data = Collections.synchronizedMap(new HashMap());

private T initialValue;

public void set(T value) {

data.put(currentKey(), value);

}

public T get() {

if (!data.containsKey(currentKey())) {

set(initialValue());

}

return data.get(currentKey());

}

public void remove() {

data.remove(currentKey());

}

/**

* 默认初始值为null, 通过重载该方法来设置默认值.

*

* @return

*/

protected T initialValue() {

return null;

}

/**

* 以当前的线程作为Map的键

*

* @return

*/

private Thread currentKey() {

return Thread.currentThread();

}

}

之后把 IdGenerator 类中使用的 ThreadLocal 替换成 DiyThreadLocal, 可以得到相同的效果.

OUTPUT:

Thread-0:1

Thread-1:1

Thread-2:1

Thread-1:2

Thread-0:2

Thread-1:3

Thread-2:2

Thread-1:4

Thread-0:3

Thread-1:5

Thread-2:3

Thread-0:4

Thread-2:4

Thread-0:5

Thread-2:5

大部分情况下使用 TheadLocal 都是不得已, 受害于依赖的类对 static 的不恰当使用. 要求相互不干扰的资源就应该使用成员变量, 自作聪明使用静态化只会导致线程不安全.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值