2

我有一个类,对于任何给定的线程只能实例化一次,通过使用 a ThreadLocal,例如:

public class MyClass {
    private static final ThreadLocal<MyClass> classInstance =
        new ThreadLocal<MyClass>() {
            @Override protected MyClass initialValue() {
                return new MyClass();
        }
    };

    private MyClass() {
    }

    public static MyClass getInstance() {
        return classInstance.get();
    }    
}

现在,我希望这些线程特定的实例可以被另一个线程访问,所以我最终得到了这种解决方案:https ://stackoverflow.com/a/5180323/1768736

这个解决方案是使用 a Map(我会选择 a ConcurrentHashMap),使用线程特定的 ID(例如 a Map<long, MyClass>)作为键。我正在考虑将其Thread.currentThread().getId()用作密钥(提供一些机制来处理线程 ID 可以重用的事实)。

但这意味着我需要公开这个线程 ID,例如:

public class MyClass {
    ...
    public long getId() {
        //return the key associated with this MyClass instance in the Map. 
        //in my case, this would be the ID of the Thread
    }
    public static MyClass getMyClass(long threadId) {
        //allow a Thread to access the MyClass instance of another Thread by providing an ID, 
        //in my case, that would be the Thread ID
    } 
}

所以我的问题是:公开 Thread 的 ID(由 Thread 返回的 ID)是一种不好的做法Thread.getId(),还是我没有什么可担心的?我不知道为什么,但我的直觉告诉我我不应该那样做。

4

2 回答 2

3

由于 Thread Id 不能用于(直接)杀死线程,因此使用起来是安全的。由于应用程序可以在创建线程时分配线程 ID,我相信它的使用只是为了帮助您在查看日志、线程转储等时调试应用程序。

此外,正如此链接所解释的,获取在 JVM 中运行的线程列表并不难。只要您知道线程 id 可以在线程死亡后重新使用,并且您的应用程序的逻辑会处理这一点,那么您应该没问题。

于 2013-07-06T15:01:31.957 回答
0

我假设您担心移动代码的安全性。否则,它似乎不会引入漏洞(ID 重用作为一个非常长的镜头)。

如果您担心移动代码的安全性,那么无论如何您都希望避免全局和线程全局状态。反正你会的。不顾一切地继续...

从安全的角度来看Maps 会导致问题,特别是如果您使用非值(例如Thread键)。恶意子类可以假装不等于自己,等于不同的线程或获得一个Threadthrough Object.equals(Object)。AnIdentityHashMap在这里是理想的,只有你可能想要一个WeakHashMap. (我不知道为什么WeakHashMap使用定义的键相等行为Map而不是IdentityHashMap.A ConcurrentWeakIdentityHashMap(“星图”)会非常好。)

在不修改的情况Thread下,您可能想要引入一个包装线程的关键对象,以提供所需的行为。

final class Key {
    private final int hash;
    private final WeakReference<Thread> ref;
    public Key(Thread thread) {
        this.hash = System.identityHashCode(thread);
        this.ref = new WeakReference<Thread>();
    }
    @Override public int hashCode() {
        return hash;
    }
    @Override public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Key)) return false;
        Key other = (Key)obj;
        Thread thread = this.ref.get();
        return thread != null && thread == other.ref.get(); 
    }
}

(您可能希望对引用进行排队,以便删除条目。)

Thread.getAllStackStraces具有安全检查,因此不受信任的代码无法全部获取。类似的调用将执行限制为可访问的线程组。

于 2013-07-08T12:06:42.110 回答