加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 08:30:41 所属栏目:Java 来源:网络整理
导读:我正在尝试使用ThreadLocal为预先存在的非线程安全类提供线程安全性,但遇到问题.似乎没有执行隔离 – 线程仍然共享静态,而不是每个线程的本地. 我相信我的用法几乎与this StackOverflow question中描述的SimpleDateFormatter的示例本地化完全平行,但它并没有
我正在尝试使用ThreadLocal为预先存在的非线程安全类提供线程安全性,但遇到问题.似乎没有执行隔离 – 线程仍然共享静态,而不是每个线程的本地.

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

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

这是我的简单课程:

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

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

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

当创建10个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.

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

解决方法

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读