如何解决ThreadLocal与ThreadPool的小矛盾?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/goldenfish1919/article/details/81978506

忽然发现还有个更牛逼的:https://github.com/alibaba/transmittable-thread-local

ThreadLocal一个很有用的场景:收到请求,框架解析出用户User对象,保存到ThreadLocal中,然后Controller、Service中就可以直接从ThreadLocal中来获取User对象了。大部分时候,这已经足够了,直到遇到了ThreadPool。ThreadPool中的线程是不会被销毁的,而且很明显跟主线程不是同一个线程,那么主线程中的ThreadLocal是无法直接传递到ThreadPool的线程里面的!再ThreadPool的场景下,显然InheritableThreadLocal是无用武之地的,下面我们就来简单的封装下。

这是我们的用来异步执行任务的ThreadPoolUtil:

public class ThreadPoolUtil {

	private final ExecutorService executor;

	private static ThreadPoolUtil instance = new ThreadPoolUtil();

	private ThreadPoolUtil() {
		this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
	}

	public static ThreadPoolUtil getInstance() {
		return instance;
	}

	public static <T> Future<T> execute(final Callable<T> runnable) {
		return getInstance().executor.submit(runnable);
	}

	public static Future<?> execute(final Runnable runnable) {
		return getInstance().executor.submit(runnable);
	}
}

既然无法直接从主线程传递到ThreadPool里面的线程,那就只能用参数来传递了:

public static abstract class ParamRunnable<T> implements Runnable{
		private T param;
		public ParamRunnable(Supplier<T> paramSupplier) {
			if(paramSupplier != null) {
				this.param = paramSupplier.get();
			}
		}
		@Override
		public void run() {
			run(param);
		}
		public abstract void run(T param);
}
	

我们创建Runnable的子类,在构造函数中把参数传递进去,这里传递一个Supplier而非参数本身,参数由Supplier提供出来,在run()方法中调用abstract的run()同时把参数传递出去。同理我们继续写一个ParamCallable:

public static abstract class ParamCallable<R,P> implements Callable<R>{
		private P param;
		public ParamCallable(Supplier<P> paramSupplier) {
			if(paramSupplier != null) {
				this.param = paramSupplier.get();
			}
		}
		@Override
		public R call() {
			return call(param);
		}
		public abstract R call(P param);
}

看一下如何来使用:

public static class User{
		private int id;
		public User() {}
		public User(int id) {
			this.id= id;
		}
		public String toString() {
			return "User [id=" + id + "]";
		}
	}
	public static class UserProvider{
		private static ThreadLocal<User> userHolder = new  ThreadLocal<User>();
		public static void setUser(User user) {
			userHolder.set(user);
		}
		public static User getUser() {
			return userHolder.get();
		}
	}
	public static void main(String[] args)throws Exception {
		UserProvider.setUser(new User(1));
		System.out.println(UserProvider.getUser());
		ThreadPoolUtil.execute(new ParamRunnable<User>(UserProvider::getUser) {
			@Override
			public void run(User user) {
				System.out.println(user);
			}
		});
		System.in.read();
	}

完整的代码见:https://github.com/xjs1919/util/blob/master/src/main/java/com/github/xjs/util/ThreadPoolUtil.java

猜你喜欢

转载自blog.csdn.net/goldenfish1919/article/details/81978506