将ThreadLocal与包含静态成员的现有类一起使用

CPe*_*ins 3 java multithreading

我正在尝试使用ThreadLocal为预先存在的非线程安全类提供线程安全性,但遇到问题.似乎没有执行隔离 - 线程仍然共享静态,而不是每个线程的本地.

我相信我的用法几乎与此StackOverflow问题SimpleDateFormatter描述的示例本地化完全平行,但它并没有按照我希望的方式运行.

我所希望的是,那些使用过它的人会指出我必须做出的令人震惊的无知错误......所以我想我的问题是:你能发现我在这里做错了什么吗?

这是我的简单课程:

public class SimpleClassWithStaticMembers {
    private static String theStaticString =
        "StaticStringInClassWithStaticMember";
    public void setTheStaticString (String val) {
        SimpleClassWithStaticMembers.theStaticString = val; 
    }
    public String getTheStaticString () {
        return SimpleClassWithStaticMembers.theStaticString;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是创建threadlocal实例的线程类SimpleClassWithStaticMembers:

public class SimpleTesterThread extends Thread {
    private void showMsg (String msg) {  
        System.out.println (msg); 
        System.out.flush(); 
    }
    public SimpleTesterThread (String threadId) {
        super(threadId);
    }
    public void run() {
        try { Thread.sleep(2000); } catch (InterruptedException ex) { }
        ThreadLocal<SimpleClassWithStaticMembers> localizedClass =
            new ThreadLocal<SimpleClassWithStaticMembers>();
        localizedClass.set(new SimpleClassWithStaticMembers());
        // repeating here to be sure we overlap all with all
        for (int ii=0; ii < 3; ii++) { 
            localizedClass.get().setTheStaticString ("Setby_" + this.getName());
            try { Thread.sleep(2000); } catch (InterruptedException ex) { }
            showMsg("            Thread [" + this.getName() + "] - " 
                + localizedClass.get().getTheStaticString() + "'.");
        }
        showMsg ("Thread [" + this.getName() 
            + "] complete. Our 'threadlocal' string is now - " 
            + localizedClass.get().getTheStaticString() + "'.");
        localizedClass.remove();
    }
}
Run Code Online (Sandbox Code Playgroud)

SimpleTesterThread创建十个实例(给它们不同的线程名称,如"AAAAAAAAAA","BBBBBBBBB"等),然后启动时,输出清楚地表明它们正在共享实例.日志输出包括:

...
            Thread [JJJJJJJJJJ] - Setby_CCCCCCCCCC'.
            Thread [DDDDDDDDDD] - Setby_JJJJJJJJJJ'.
            Thread [IIIIIIIIII] - Setby_DDDDDDDDDD'.
            Thread [GGGGGGGGGG] - Setby_IIIIIIIIII'.
            Thread [EEEEEEEEEE] - Setby_GGGGGGGGGG'.
Thread [EEEEEEEEEE] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
            Thread [HHHHHHHHHH] - Setby_GGGGGGGGGG'.
            Thread [BBBBBBBBBB] - Setby_GGGGGGGGGG'.
            Thread [FFFFFFFFFF] - Setby_GGGGGGGGGG'.
Thread [FFFFFFFFFF] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
...
            Thread [JJJJJJJJJJ] - Setby_GGGGGGGGGG'.
Thread [JJJJJJJJJJ] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
Thread [HHHHHHHHHH] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
            Thread [GGGGGGGGGG] - Setby_GGGGGGGGGG'.
Thread [GGGGGGGGGG] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
            Thread [IIIIIIIIII] - Setby_GGGGGGGGGG'.
            Thread [CCCCCCCCCC] - Setby_GGGGGGGGGG'.
Thread [CCCCCCCCCC] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
Thread [AAAAAAAAAA] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
            Thread [DDDDDDDDDD] - Setby_GGGGGGGGGG'.
Thread [DDDDDDDDDD] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
Thread [IIIIIIIIII] complete. Our 'threadlocal' string is now - Setby_GGGGGGGGGG'.
============== all threads complete.

我没有包含创建,启动和加入线程的类 - 如果感觉有用,我很乐意编辑添加它.

Tom*_*ine 5

具有单独的实例没有帮助,因为所有实例都是相同的静态字段.可变的静力学是邪恶的.

如果你真的无法改变类,你可能只想使用一个锁,这样每个客户端就可以一次使用一个静态字段.如果你想拥有静态字段的不同实例,那么你可能需要使用类加载器(另一个明显的解决方案是重写字节码,这更不令人愉快).