【问题标题】:Pass ThreadLocal class to another thread?将 ThreadLocal 类传递给另一个线程?
【发布时间】:2017-11-08 11:29:47
【问题描述】:

我在我的 Java 程序中使用 ThreadLocal,以便通过线程获取和设置某些数据成员。

我有一堂课,内容如下

public class ThreadLocalManager {
    public static final ThreadLocal<String> accountUsername = new ThreadLocal<String>();
    public static final ThreadLocal<String> accountPassword = new ThreadLocal<String>();
    public static final ThreadLocal<Long> accountId = new ThreadLocal<Long>();
    .....................
    .....................
    .....................

}

我在多线程应用程序中一直在使用它,没有任何问题。现在每个线程都将创建另一个线程,我希望将 ThreadLocalManager 传递给创建的新线程。这将如何完成?

【问题讨论】:

标签: java multithreading


【解决方案1】:

编辑:我根据我的原始建议(如下)修改了我的示例代码以使用InheritableThreadLocal,我发现它更简单,所以添加更新的代码。

这是更新后的 ThreadLocalManager:

package inheritableThreadLocal;

public class ThreadLocalManager {
    public static final InheritableThreadLocal<String> accountUsername = new InheritableThreadLocal<String>();
    public static final InheritableThreadLocal<String> accountPassword = new InheritableThreadLocal<String>();
    public static final InheritableThreadLocal<Long> accountId = new InheritableThreadLocal<Long>();
}

我还更新了Runner(见下文),但现在它的唯一目的是打印变量的值:

package inheritableThreadLocal;

public class Runner implements Runnable{

    @Override
    public void run() {
        System.out.println("Inside Runner's run");
        System.out.println(ThreadLocalManager.accountId.get());
        System.out.println(ThreadLocalManager.accountUsername.get());
        System.out.println(ThreadLocalManager.accountPassword.get());
    }

}

终于更新了包含main方法的类:

package inheritableThreadLocal;

public class ThreadLocalMain {

    public static void main(String[] args) {
        System.out.println("At start of main");
        System.out.println(ThreadLocalManager.accountId.get());
        System.out.println(ThreadLocalManager.accountUsername.get());
        System.out.println(ThreadLocalManager.accountPassword.get());

        Thread t1 = new Thread(new Runnable(){

            @Override
            public void run() {
                ThreadLocalManager.accountId.set(new Long(12345));
                ThreadLocalManager.accountUsername.set("user1");
                ThreadLocalManager.accountPassword.set("pass1");

                System.out.println("In t1 run");
                System.out.println(ThreadLocalManager.accountId.get());
                System.out.println(ThreadLocalManager.accountUsername.get());
                System.out.println(ThreadLocalManager.accountPassword.get());

                Thread t2 = new Thread(new Runner());
                t2.start();
            }

        });
        t1.start();
    }

}

原建议:

因此,您可以使用 Runnable 对象创建新的 Thread 对象。如果您这样做,您可以创建实现Runnable 的自定义对象,并且可以保存ThreadLocal 变量的值,直到新的Thread 启动。一旦新的Thread 启动(即调用run 方法),这些自定义Runnable 对象就会设置ThreadLocal 变量。

这是一个我为此创建的主类:

package threadLocal;

public class ThreadLocalMain {

    public static void main(String[] args) {
        System.out.println("At start of main");
        System.out.println(ThreadLocalManager.accountId.get());
        System.out.println(ThreadLocalManager.accountUsername.get());
        System.out.println(ThreadLocalManager.accountPassword.get());

        Thread t1 = new Thread(new Runnable(){

            @Override
            public void run() {
                ThreadLocalManager.accountId.set(new Long(12345));
                ThreadLocalManager.accountUsername.set("user1");
                ThreadLocalManager.accountPassword.set("pass1");

                System.out.println("In t1 run");
                System.out.println(ThreadLocalManager.accountId.get());
                System.out.println(ThreadLocalManager.accountUsername.get());
                System.out.println(ThreadLocalManager.accountPassword.get());

                Thread t2 = new Thread(new Runner(ThreadLocalManager.accountUsername.get(),
                        ThreadLocalManager.accountPassword.get(),
                        ThreadLocalManager.accountId.get()));
                t2.start();
            }

        });
        t1.start();
    }

}

为了完整起见,这里是我使用的 ThreadLocalManager:

package threadLocal;

public class ThreadLocalManager {
    public static final ThreadLocal<String> accountUsername = new ThreadLocal<String>();
    public static final ThreadLocal<String> accountPassword = new ThreadLocal<String>();
    public static final ThreadLocal<Long> accountId = new ThreadLocal<Long>();
}

最后,这是我创建的自定义Runnable

package threadLocal;

public class Runner implements Runnable{

    private String userName, password;
    private long acctId;

    public Runner(String user, String pword, long accountId){
        System.out.println("In Runner constructor");
        System.out.println(ThreadLocalManager.accountId.get());
        System.out.println(ThreadLocalManager.accountUsername.get());
        System.out.println(ThreadLocalManager.accountPassword.get());

        userName = user;
        password = pword;
        acctId = accountId;
    }

    @Override
    public void run() {
        System.out.println("Inside Runner's run");
        System.out.println(ThreadLocalManager.accountId.get());
        System.out.println(ThreadLocalManager.accountUsername.get());
        System.out.println(ThreadLocalManager.accountPassword.get());

        ThreadLocalManager.accountId.set(acctId);
        ThreadLocalManager.accountUsername.set(userName);
        ThreadLocalManager.accountPassword.set(password);

        System.out.println("Inside Runner's run - after setting");
        System.out.println(ThreadLocalManager.accountId.get());
        System.out.println(ThreadLocalManager.accountUsername.get());
        System.out.println(ThreadLocalManager.accountPassword.get());
    }

}

此代码将ThreadLocal 变量的值传递给Runner 实例,然后Runner 实例用于创建一个新的Thread(如果您运行代码,您将看到它没有值首先是ThreadLocal 变量)。然后Runner 设置ThreadLocal 变量,您可以从控制台输出中看到它们与 t1 的匹配。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 2011-04-27
    • 2014-02-24
    • 2013-12-10
    • 2013-07-24
    • 1970-01-01
    相关资源
    最近更新 更多