Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ConcurrentHashMap支持的队列的线程安全 import java.util.Map; 导入java.util.concurrent.ConcurrentHashMap; 导入java.util.concurrent.Future; 导入org.slf4j.Logger; 导入org.slf4j.LoggerFactory; 公共类DedupingQueue实现QueueWrapper{ 私有静态最终记录器Logger=LoggerFactory.getLogger(duplicatingqueue.class); 私有最终映射项beingworkedon=新的ConcurrentHashMap(); private final AsyncWorker AsyncWorker;//包含线程池支持的异步方法 公共重复数据队列(AsyncWorker AsyncWorker){ this.asyncWorker=asyncWorker; } @凌驾 公共未来提交(E){ 如果(!itemsBeingWorkedOn.containsKey(e)){ itemsBeingWorkedOn.put(e,asyncWorker.executeWorkAsync(e,this)); }否则{ debug(“拒绝[{}],因为它已经在处理中”,e); } 返回正在处理的项目get(e); } @凌驾 公开作废完成(E){ debug(“Completed[{}]”,e); 正在处理的项目移除(e); } @凌驾 公共空间拒绝和审判(E){ itemsBeingWorkedOn.putIfAbsent(e,asyncWorker.executeWorkAsync(e,this)); } }_Java_Multithreading - Fatal编程技术网

ConcurrentHashMap支持的队列的线程安全 import java.util.Map; 导入java.util.concurrent.ConcurrentHashMap; 导入java.util.concurrent.Future; 导入org.slf4j.Logger; 导入org.slf4j.LoggerFactory; 公共类DedupingQueue实现QueueWrapper{ 私有静态最终记录器Logger=LoggerFactory.getLogger(duplicatingqueue.class); 私有最终映射项beingworkedon=新的ConcurrentHashMap(); private final AsyncWorker AsyncWorker;//包含线程池支持的异步方法 公共重复数据队列(AsyncWorker AsyncWorker){ this.asyncWorker=asyncWorker; } @凌驾 公共未来提交(E){ 如果(!itemsBeingWorkedOn.containsKey(e)){ itemsBeingWorkedOn.put(e,asyncWorker.executeWorkAsync(e,this)); }否则{ debug(“拒绝[{}],因为它已经在处理中”,e); } 返回正在处理的项目get(e); } @凌驾 公开作废完成(E){ debug(“Completed[{}]”,e); 正在处理的项目移除(e); } @凌驾 公共空间拒绝和审判(E){ itemsBeingWorkedOn.putIfAbsent(e,asyncWorker.executeWorkAsync(e,this)); } }

ConcurrentHashMap支持的队列的线程安全 import java.util.Map; 导入java.util.concurrent.ConcurrentHashMap; 导入java.util.concurrent.Future; 导入org.slf4j.Logger; 导入org.slf4j.LoggerFactory; 公共类DedupingQueue实现QueueWrapper{ 私有静态最终记录器Logger=LoggerFactory.getLogger(duplicatingqueue.class); 私有最终映射项beingworkedon=新的ConcurrentHashMap(); private final AsyncWorker AsyncWorker;//包含线程池支持的异步方法 公共重复数据队列(AsyncWorker AsyncWorker){ this.asyncWorker=asyncWorker; } @凌驾 公共未来提交(E){ 如果(!itemsBeingWorkedOn.containsKey(e)){ itemsBeingWorkedOn.put(e,asyncWorker.executeWorkAsync(e,this)); }否则{ debug(“拒绝[{}],因为它已经在处理中”,e); } 返回正在处理的项目get(e); } @凌驾 公开作废完成(E){ debug(“Completed[{}]”,e); 正在处理的项目移除(e); } @凌驾 公共空间拒绝和审判(E){ itemsBeingWorkedOn.putIfAbsent(e,asyncWorker.executeWorkAsync(e,this)); } },java,multithreading,Java,Multithreading,我很难推理上述代码的线程安全性 我认为complete和rejectAndretry是完全线程安全的,因为map是线程安全的。但是如果AsyncWorker本身不是线程安全的,那么submit呢?另外,我如何才能以最有效的方式使其线程安全,而不使用synchronized(使用ConcurrentHashMap的内置保证)?submit()不是线程安全的,因为您的check-then-act序列不是原子的。一个线程的特定键的状态可以在检查之后和调用之前由另一个线程更改。使用ConcurrentH

我很难推理上述代码的线程安全性

我认为
complete
rejectAndretry
是完全线程安全的,因为map是线程安全的。但是如果
AsyncWorker
本身不是线程安全的,那么
submit
呢?另外,我如何才能以最有效的方式使其线程安全,而不使用
synchronized
(使用ConcurrentHashMap的内置保证)

submit()
不是线程安全的,因为您的check-then-act序列不是原子的。一个线程的特定键的状态可以在检查之后和调用之前由另一个线程更改。使用ConcurrentHashMap中的原子方法(很可能是
computeIfAbsent()
)修复此问题

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DedupingQueue<E> implements QueueWrapper<E> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DedupingQueue.class);

private final Map<E, Future<E>> itemsBeingWorkedOn = new ConcurrentHashMap<>();
private final AsyncWorker<E> asyncWorker; //contains async method backed by a thread pool

public DedupingQueue(AsyncWorker<E> asyncWorker) {
    this.asyncWorker = asyncWorker;
}

@Override
public Future<E> submit(E e) {
    if (!itemsBeingWorkedOn.containsKey(e)) {
        itemsBeingWorkedOn.put(e, asyncWorker.executeWorkAsync(e, this));
    } else {
        LOGGER.debug("Rejected [{}] as it's already being worked on", e);
    }
    return itemsBeingWorkedOn.get(e);
}

@Override
public void complete(E e) {
    LOGGER.debug("Completed [{}]", e);
    itemsBeingWorkedOn.remove(e);
}

@Override
public void rejectAndRetry(E e) {
    itemsBeingWorkedOn.putIfAbsent(e, asyncWorker.executeWorkAsync(e, this));
}

}
如果
AsyncWorker
不是线程安全的,那么整个类也不是线程安全的。但是,如果没有
AsyncWorker
源代码,就很难对其进行推理。

submit()
不是线程安全的,因为您的check-then-act序列不是原子的。一个线程的特定键的状态可以在检查之后和调用之前由另一个线程更改。使用ConcurrentHashMap中的原子方法(很可能是
computeIfAbsent()
)修复此问题

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DedupingQueue<E> implements QueueWrapper<E> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DedupingQueue.class);

private final Map<E, Future<E>> itemsBeingWorkedOn = new ConcurrentHashMap<>();
private final AsyncWorker<E> asyncWorker; //contains async method backed by a thread pool

public DedupingQueue(AsyncWorker<E> asyncWorker) {
    this.asyncWorker = asyncWorker;
}

@Override
public Future<E> submit(E e) {
    if (!itemsBeingWorkedOn.containsKey(e)) {
        itemsBeingWorkedOn.put(e, asyncWorker.executeWorkAsync(e, this));
    } else {
        LOGGER.debug("Rejected [{}] as it's already being worked on", e);
    }
    return itemsBeingWorkedOn.get(e);
}

@Override
public void complete(E e) {
    LOGGER.debug("Completed [{}]", e);
    itemsBeingWorkedOn.remove(e);
}

@Override
public void rejectAndRetry(E e) {
    itemsBeingWorkedOn.putIfAbsent(e, asyncWorker.executeWorkAsync(e, this));
}

}
如果
AsyncWorker
不是线程安全的,那么整个类也不是线程安全的。但是,如果没有
AsyncWorker
源代码,就很难对其进行推理。

compute()
方法,该函数获取键、当前值或
null
(如果没有当前映射),并返回要保留在映射中的值,或者在返回
null
时将其删除

if (!itemsBeingWorkedOn.containsKey(e)) {
    itemsBeingWorkedOn.put(e, asyncWorker.executeWorkAsync(e, this));
}
@覆盖
公共未来提交(E){
returnitemsbeingworkedon.compute(e,(k,v)->{
如果(v==null){
返回asyncWorker.executeWorkAsync(k,this);
}否则{
debug(“拒绝[{}],因为它已经在处理中”,k);
返回v;
}
});
}

请注意,您的队列没有排序。如果您需要FIFO或后进先出顺序,您应该使用更合适的数据结构,例如带有同步语句的
LinkedHashMap

compute()
方法,该方法使用键、当前值或
null
,如果没有当前映射,并返回要保留在映射中的值,如果返回
null
,则将其删除

if (!itemsBeingWorkedOn.containsKey(e)) {
    itemsBeingWorkedOn.put(e, asyncWorker.executeWorkAsync(e, this));
}
@覆盖
公共未来提交(E){
returnitemsbeingworkedon.compute(e,(k,v)->{
如果(v==null){
返回asyncWorker.executeWorkAsync(k,this);
}否则{
debug(“拒绝[{}],因为它已经在处理中”,k);
返回v;
}
});
}


请注意,您的队列没有排序。如果您需要FIFO或LIFO顺序,您应该使用更合适的数据结构,例如
LinkedHashMap
synchronized
语句。

线程安全性取决于您期望的行为。如果覆盖现有密钥和/或不返回相同的值是可以的,那么
submit()
是线程安全的。线程安全取决于您期望的行为。如果覆盖现有密钥和/或不返回相同的值是可以的,则
submit()
是线程安全的。部分学分。关于序列不是原子的,您是正确的,但是
putIfAbsent
不合适,因为它仍然会始终执行
asyncWorker.executeWorkAsync(e,this)
,但不一定要将它放在映射中。因此需要
compute()
computeIfAbsent()
AsyncWorker
的线程安全性不会影响整个类,特别是
complete
rejectAndRetry
(问题中也指出了这一点)。谢谢,你说得对,
putIfAbsent
在这里不起作用,应该使用
computeifassent
。我有疑问,所以写了“原子方法”。将编辑我的答案。关于第二部分,我从未见过关于特定类方法的线程安全性的推理,从类逻辑中也可以清楚地看出,如果没有
submit()
,其他方法就没有意义。Plus
rejectAndRetry()
还使用了
AsyncWorker
。由于
remove()
是线程安全的,因此
complete()
在逻辑上是线程安全的。不过,您可能会得到一条重复的日志记录行,因此严格来说,它不是线程安全的。仔细观察
拒绝和重试
,我无法真正理解它的预期用途。另外,使用非线程安全的
submit()
可以使用相同的密钥完成并重试另一个线程任务,而不是原来的任务。是的,
submit()
不是线程安全的。那是确定的,部分信用。你