如何解决java:在多线程中从 TreeMap 访问值时出现问题
我使用 TreeMap 来存储键值。 对于使用自定义对象的键。 但是一旦我遇到非常奇怪的问题,我就无法获得我之前设置的值(使用相同的键)。 下面是我的代码
public final class TestOptions implements Cloneable {
private Map<StorageSystemOptionKey,Object> options = new TreeMap<StorageSystemOptionKey,Object>();
private static final class StorageSystemOptionKey implements Comparable<StorageSystemOptionKey> {
/** Constant used to create hashcode */
private static final int HASH = 31;
private final Class<? extends StorageRepository> storageRepositoryClass;
/** The option name */
private final String name;
private StorageSystemOptionKey(Class<? extends StorageRepository> storageRepositoryClass,String name) {
this.storageRepositoryClass = storageRepositoryClass;
this.name = name;
}
public int compareto(StorageSystemOptionKey o) {
int ret = storageRepositoryClass.getName().compareto(o.storageRepositoryClass.getName());
if (ret != 0) {
return ret;
}
return name.compareto(o.name);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final StorageSystemOptionKey that = (StorageSystemOptionKey) o;
if (!storageRepositoryClass.equals(that.storageRepositoryClass)) {
return false;
}
if (!name.equals(that.name)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result;
result = storageRepositoryClass.hashCode();
result = HASH * result + name.hashCode();
return result;
}
}
void setoption(Class<? extends StorageRepository> fileSystemClass,String name,Object value) {
options.put(new StorageSystemOptionKey(fileSystemClass,name),value);
}
Object getoption(Class<? extends StorageRepository> fileSystemClass,String name) {
StorageSystemOptionKey key = new StorageSystemOptionKey(fileSystemClass,name);
return options.get(key);
}
boolean hasOption(Class<? extends StorageRepository> fileSystemClass,name);
return options.containsKey(key);
}
public int compareto(TestOptions other) {
if (this == other) {
return 0;
}
int propsSz = options == null ? 0 : options.size();
int propsFkSz = other.options == null ? 0 : other.options.size();
if (propsSz < propsFkSz) {
return -1;
}
if (propsSz > propsFkSz) {
return 1;
}
if (propsSz == 0) {
return 0;
}
int hash = options.hashCode();
int hashFk = other.options.hashCode();
if (hash < hashFk) {
return -1;
}
if (hash > hashFk) {
return 1;
}
return 0;
}
@Override
public Object clone() {
TestOptions clone = new TestOptions();
clone.options = new TreeMap<StorageSystemOptionKey,Object>(options);
return clone;
}
}
public abstract Class<? extends StorageRepository> getStorageRepositoryClass();
public Class<? extends StorageRepository> getStorageRepositoryClass() {
return MyImpl.class;
}
TestOptions opt =new TestOptions(); // shared accross all Threads
Object getProperty(String name) {
return opt.getoption(getStorageRepositoryClass(),name);
}
void setProperty(String name,Object value) {
opt.setoption(getStorageRepositoryClass(),name,value);
}
在多线程应用程序中使用 set 和 get 方法。
查询:
我多次调用 set/get 然后我也无法获得之前设置的值(相同的键)
这是因为Treeset 实现不同步
或者 hashCode、equals 或 compareto 方法实现的问题?
解决方法
TreeSet 未同步。我相信 ConcurrentSkipListMap 可能会更好。
,快速浏览一下您的 compareTo()
、equals()
和 hashCode()
看起来不错。请注意,TreeMap
将主要使用 compareTo()
来查找元素,因此该方法需要是正确的(您的看起来技术上是正确的)。
然而,TreeMap
和 TreeSet
(以及其他基本集合和映射)不是线程安全的,因此并发修改会导致各种意外行为。我们曾经遇到过这样的情况,其中 2 个线程试图将单个元素添加到 hashmap 并且线程最终陷入无限循环,因为解决冲突的内部列表产生了一个循环(由于并发 put)。
因此,要么使用 ConcurrentXxxx
地图和集合,要么同步访问您的地图和集合。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。