- 每个线程需要独享的对象,且这个对象是线程不安全的,所以需要ThreadLocal给每个线程复制一份 eg:Random、SimpleDateFormat 都是线程不安全的;
以下代码是通过线程池来打印各个线程的时间
`
public static ExecutorService executorService = Executors.newFixedThreadPool(10);
public static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
int finalI = i;
executorService.submit(new Runnable() {
@Override
public void run() {
Date date = TenThreadTest.date(finalI);
System.out.println(simpleDateFormat.format(date));
}
});
}
executorService.shutdown();
}
public static Date date (int seconds) {
return new Date(1000 * seconds);
}
`
以上代码执行结果
`
1970-01-01 08:00:02
1970-01-01 08:00:06
1970-01-01 08:00:05
1970-01-01 08:00:02
1970-01-01 08:00:02
1970-01-01 08:00:08
1970-01-01 08:00:02
1970-01-01 08:00:02
1970-01-01 08:00:09
1970-01-01 08:00:07
`
大家有没有发现一个问题就是执行结果中存在重复的时间,根本原因就是 SimpleDateFormat 是线程不安全的,所有的线程共SimpleDateFormat,我们可以通过synchronized加锁,但是synchronized是阻塞的,如果线程的任务量特别大,效率会特别低;
以下是通过ThreadLocal加持过得实现方式:
十个线程都会有自己的 SimpleDateFormat 都是线程独享的
`
public static ExecutorService executorService = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
int finalI = i;
executorService.submit(new Runnable() {
@Override
public void run() {
SimpleDateFormat simpleDateFormat = ThreadLocalFormat.simpleDateFormatThreadLocal.get();
Date date = TenThreadTest.date(finalI);
System.out.println(simpleDateFormat.format(date));
}
});
}
executorService.shutdown();
}
public static Date date (int seconds) {
return new Date(1000 * seconds);
}
static class ThreadLocalFormat {
public static ThreadLocal<SimpleDateFormat> simpleDateFormatThreadLocal = ThreadLocal.withInitial(() ->
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
}
`
- 每个线程内需要全局变量,不需要传参,可以让不同的方法直接使用
以下代码让当前用户在当前线程畅通无阻,不需要层层传递参数
`
package thread;
public class UsePart2 {
public static void main(String[] args) {
User user = new User();
user.setName("王哈哈");
UserContentHolder.threadLocal.set(user);
new Service1().process();
new Service2().process();
new Service3().process();
}
}
class Service1 {
public void process() {
System.out.println("service1" + UserContentHolder.threadLocal.get().getName());
}
}
class Service2 {
public void process() {
System.out.println("service2" + UserContentHolder.threadLocal.get().getName());
}
}
class Service3 {
public void process() {
System.out.println("service3" + UserContentHolder.threadLocal.get().getName());
}
}
class UserContentHolder{
public static ThreadLocal<User> threadLocal = new ThreadLocal<User>();
}
class User {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
`
运行结果:
`
service1王哈哈
service2王哈哈
service3王哈哈
`