简体   繁体   English

将ThreadLocal类传递给另一个线程?

[英]Pass ThreadLocal class to another thread?

I'm using ThreadLocal within my Java program inorder to get and set certain data members through out the thread. 我在Java程序中使用ThreadLocal以便通过线程获取和设置某些数据成员。

I have a class with the following content 我有一堂课,内容如下

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>();
    .....................
    .....................
    .....................

}

I have been using this with no problems in my multi threaded application. 我在多线程应用程序中一直没有问题地使用它。 Now each thread will be creating another thread and I want ThreadLocalManager to be passed to the new thread that was created. 现在,每个线程都将创建另一个线程,我希望将ThreadLocalManager传递给创建的新线程。 How would this be done? 怎么做?

EDIT: I modified my example code from my original suggestion (below) to use InheritableThreadLocal and I find it to be much simpler so adding the updated code. 编辑:我修改了我的原始建议(以下)中的示例代码,以使用InheritableThreadLocal ,我发现它要简单得多,因此添加了更新的代码。

Here is the updated ThreadLocalManager: 这是更新的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>();
}

I also updated Runner (see original below) but now its only purpose is to print the values of the variables: 我还更新了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());
    }

}

Finally the updated class containing the main method: 最后,更新后的类包含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();
    }

}

Original Suggestion: 原始建议:

So you could create your new Thread objects by using Runnable objects. 因此,您可以使用Runnable对象创建新的Thread对象。 If you do that you can create custom objects that implement Runnable and can hold the values of the ThreadLocal variables until the new Thread is started. 如果这样做,则可以创建实现Runnable并可以保存ThreadLocal变量的值的自定义对象,直到启动新的Thread Once the new Thread starts (ie run method is called) these custom Runnable objects set the ThreadLocal variables. 一旦新Thread启动(即调用run方法),这些自定义Runnable对象将设置ThreadLocal变量。

Here's a class with a main I created for this: 这是我为此创建的一个主类的类:

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();
    }

}

For completeness here's the ThreadLocalManager I used: 为了完整起见,这是我使用的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>();
}

Lastly, here is the custom Runnable I created: 最后,这是我创建的自定义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());
    }

}

This code passes the values of the ThreadLocal variables into the Runner instance and then the Runner instance is used to create a new Thread (which as you will see if you run the code has no values for the ThreadLocal variables at first). 这段代码将ThreadLocal变量的值传递到Runner实例中,然后使用Runner实例创建一个新的Thread (如您所见,如果您运行代码,最初将没有ThreadLocal变量的值)。 Then the Runner sets the ThreadLocal variables and as you can see from the console output they match what t1 had. 然后, Runner设置ThreadLocal变量,并且如您从控制台输出中所见,它们与t1匹配。

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM