Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
Java 延迟队列意外行为。DrainTo仅从队列中删除1个过期项目_Java_Multithreading_Priority Queue_Java.util.concurrent_Blockingqueue - Fatal编程技术网

Java 延迟队列意外行为。DrainTo仅从队列中删除1个过期项目

Java 延迟队列意外行为。DrainTo仅从队列中删除1个过期项目,java,multithreading,priority-queue,java.util.concurrent,blockingqueue,Java,Multithreading,Priority Queue,Java.util.concurrent,Blockingqueue,我想遍历延迟队列中未过期的元素。 类事务实现了Delayed,并有一个字段timestamp,它表示事务在UTC发起时的时间戳(而不是当前时间戳) 公共类事务实现延迟{ 私人最终双倍金额; private final Long timestamp;//创建项并发送到此处的时间戳 公开交易(双倍金额,长时间戳){ 这个。金额=金额; this.timestamp=时间戳; } @凌驾 公共长getDelay(时间单位){ 长延迟=单位.convert(一分钟-(System.currentTime

我想遍历延迟队列中未过期的元素。 类事务实现了Delayed,并有一个字段timestamp,它表示事务在UTC发起时的时间戳(而不是当前时间戳)

公共类事务实现延迟{
私人最终双倍金额;
private final Long timestamp;//创建项并发送到此处的时间戳
公开交易(双倍金额,长时间戳){
这个。金额=金额;
this.timestamp=时间戳;
}
@凌驾
公共长getDelay(时间单位){
长延迟=单位.convert(一分钟-(System.currentTimeMillis()-时间戳),时间单位.毫秒);
返回延迟;
}
@凌驾
公共内部比较(延迟){
如果(延迟==此){
返回0;
}
if(事务的延迟实例){
返回0;
}
long diff=(getDelay(TimeUnit.millides)-delayed.getDelay(TimeUnit.millides));
返回值((差异==0)?0:((差异<0)?-1:1));
}
@凌驾
公共int hashCode(){
最终整数素数=31;
int结果=1;
result=prime*result+timestamp.hashCode();
返回结果;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj){
返回true;
}
if(obj==null){
返回false;
}
如果(!(obj事务实例)){
返回false;
}
最终交易其他=(交易)obj;
返回timestamp.equals(其他timestamp);
}
}
下面的TransactionManager类将传入事务添加到队列中,如果新的传入事务小于1分钟。 在getStatistics上,旧事务应该从队列中删除,并且队列应该只包含小于1分钟的事务

public class TransactionManager {

    private DelayQueue<Transaction> transactions;


    public TransactionManager() {
        transactions = new DelayQueue<>();
        System.setProperty("user.timezone", "UTC");
    }

    public Object createTransaction(String json) {
        JSONObject jsonObject = null;
        try {
            jsonObject = JsonValidator.validateTransactionJson(json);
        } catch (Exception ex) {
            return new ResponseEntity(HttpStatus.UNPROCESSABLE_ENTITY);
        }
        long delay = System.currentTimeMillis() - ((Long) jsonObject.get(TIMESTAMP));
        if (delay > ONEMINUTE) {
            return new ResponseEntity(HttpStatus.NO_CONTENT);
        }
        transactions.add(new Transaction((Double) jsonObject.get(AMOUNT), (Long) jsonObject.get(TIMESTAMP)));
        return new ResponseEntity(HttpStatus.OK);
    }

    public long getStatistics() {
        List<Transaction> tempForCleaning = new ArrayList<>();
        transactions.drainTo(tempForCleaning);
        tempForCleaning.clear();
        StatisticJSON statistics = new StatisticJSON();
        transactions.stream().forEach(transaction -> {
            statistics.setCount(statistics.getCount() + 1);
        });
        return statistics.getCount();
    }
}
公共类事务管理器{
私有延迟队列事务;
公共事务管理器(){
事务=新的延迟队列();
System.setProperty(“用户时区”、“UTC”);
}
公共对象createTransaction(字符串json){
JSONObject JSONObject=null;
试一试{
jsonObject=JsonValidator.validateTransactionJson(json);
}捕获(例外情况除外){
返回新的ResponseEntity(HttpStatus.UNPROCESSABLE_实体);
}
长延迟=System.currentTimeMillis()-((长)jsonObject.get(时间戳));
如果(延迟>一分钟){
返回新的响应属性(HttpStatus.NO_内容);
}
添加(新事务((Double)jsonObject.get(AMOUNT),(Long)jsonObject.get(TIMESTAMP));
返回新的响应状态(HttpStatus.OK);
}
公共长期统计数据(){
List tempForCleaning=new ArrayList();
事务处理。拖入(临时清理);
tempForCleaning.clear();
StatisticJSON statistics=new StatisticJSON();
transactions.stream().forEach(事务->{
statistics.setCount(statistics.getCount()+1);
});
返回statistics.getCount();
}
}
在这个测试中,我在40秒之前创建了5个事务,在10秒之前创建了3个事务。 因此,等待45秒后,前5个事务应该被清空,队列应该只包含3个事务,然而,方法drainTo只删除1个旧事务

@Test
public void test() {
    DateTime dateTime = new DateTime(DateTimeZone.UTC);
    long fortyMilliSecondsAgo = dateTime.minusSeconds(40).getMillis();
    long twentyMilliSecondsAgo = dateTime.minusSeconds(10).getMillis();
    for (int i = 0; i < 5; i++) {
        createTransaction(fortyMilliSecondsAgo);
    }
    for (int i = 0; i < 3; i++) {
        createTransaction(twentyMilliSecondsAgo);
    }
    Assert.assertTrue(transactionManager.getStatistics() == 8);
    try {
        TimeUnit.SECONDS.sleep(45);
        System.out.println("\n\n\n");
        Assert.assertTrue(transactionManager.getStatistics() == 3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private void createTransaction(long timestamp) {
    transactionManager.createTransaction("{\"amount\":100.0,\"timestamp\":" + timestamp + "}");
}
@测试
公开无效测试(){
DateTime DateTime=新的日期时间(DateTimeZone.UTC);
long-fortymillissecondsago=dateTime.minusSeconds(40).getMillis();
long Twenty毫秒sago=dateTime.minusSeconds(10).getMillis();
对于(int i=0;i<5;i++){
createTransaction(fortymillissecondsago);
}
对于(int i=0;i<3;i++){
createTransaction(二十毫秒sago);
}
Assert.assertTrue(transactionManager.getStatistics()==8);
试一试{
时间单位。秒。睡眠(45);
System.out.println(“\n\n\n”);
Assert.assertTrue(transactionManager.getStatistics()==3);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
私有void createTransaction(长时间戳){
createTransaction(“{\'金额\':100.0,\'时间戳\':“+时间戳+”}”);
}
我错过了一些东西,为什么德兰托只删除了一个过期的项目,即使还有4个,但无法捕捉到

if (delayed instanceof Transaction) { return 0; }
看起来不正确-如果希望
compareTo
getDelay()
保持一致,可能应该删除该位。因此,您的方法可能如下所示(使用静态导入):


谢谢,你说得很对,那部分我看不见:)
if (delayed instanceof Transaction) { return 0; }
public int compareTo(Delayed delayed) {
  return delayed == this
    ? 0
    : Long.compare(getDelay(MILLISECONDS), delayed.getDelay(MILLISECONDS));
}