如何在不使用InheritableThreadLocal的情况下为每个顶级进程/线程创建共享上下文?

Jef*_*erg 7 java multithreading

我想看看是否有一个很好的模式,可以在不使用顶级线程的所有类和子线程的情况下共享上下文InheritableThreadLocal.

我有几个顶级进程,每个进程都在自己的线程中运行.这些顶级进程通常会产生临时子线程.

我希望每个顶级流程都拥有并管理自己的数据库连接.

希望绕过从类类数据库连接,并从线程的子线程(我的同事这个所谓的"社区自行车"模式).这些是大型顶级进程,这意味着可能会编辑数百个方法签名来传递此数据库连接.

现在我调用单例来获取数据库连接管理器.单例使用,InheritableThreadLocal以便每个顶级进程都有自己的版本.虽然我知道有些人对单身人士有问题,但这意味着DBConnector.getDBConnection(args)只要我需要正确管理的连接,我就可以说(换句话说).如果我能找到一个更好但仍然干净的解决方案,我不会依赖这种方法.

由于各种原因InheritableThreadLocal被证明是棘手的.(见这个问题.)

有没有人有一个建议来处理这种不需要或者InheritableThreadLocal遍布某个上下文对象的东西?

谢谢你的帮助!


更新:我设法解决了眼前的问题(请参阅相关问题),但我仍然希望了解其他可能的方法.下面的四十二个建议是好的,并且确实有效(谢谢!),但请参阅评论为什么它有问题.如果人们投票支持jtahlborn的答案并告诉我,我因为想要避免绕过我的数据库连接而迷恋,那么我会松懈,选择那个作为我的答案,并修改我的世界观.

for*_*two 3

我还没有对此进行测试,但想法是创建一个自定义的 ThreadPoolExecutor,它知道如何获取上下文对象并使用 #beforeExecute() 将上下文对象传输到将要执行任务的线程。要成为一个好公民,您还应该清除 #afterEXecute() 中的上下文对象,但我将其作为练习。

public class XyzThreadPoolExecutor extends ThreadPoolExecutor  {

public XyzThreadPoolExecutor() {
    super(3, 3, 100, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new MyThreadFactory());
}

@Override
public void execute(Runnable command) {
    /*
     * get the context object from the calling thread
     */
    Object context = null;
    super.execute(new MyRunnable(context, command));
}

@Override
protected void beforeExecute(Thread t, Runnable r) {
    ((MyRunnable)r).updateThreadLocal((MyThread) t);
    super.beforeExecute(t, r);
}

private static class MyThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        return new MyThread(r);
    }

}

private class MyRunnable implements Runnable {
    private final Object context;
    private final Runnable delegate;

    public MyRunnable(Object context, Runnable delegate) {
        super();
        this.context = context;
        this.delegate = delegate;
    }

    void updateThreadLocal(MyThread thread) {
        thread.setContext(context);
    }

    @Override
    public void run() {
        delegate.run();

    }
}

private static class MyThread extends Thread {

    public MyThread(Runnable target) {
        super(target);
    }

    public void setContext(Object context) {
        // set the context object here using thread local
    }

}
}
Run Code Online (Sandbox Code Playgroud)