首页 \ 问答 \ java.util.concurrent.DelayQueue忽略过期的元素(java.util.concurrent.DelayQueue overlooking expired elements)

java.util.concurrent.DelayQueue忽略过期的元素(java.util.concurrent.DelayQueue overlooking expired elements)

下面的Java代码示例使用java DelayQueue来处理任务。 但是,从另一个线程插入任务似乎会破坏(我的)预期行为。

请道歉,代码示例很长,但总结如下:

  1. 主线程向DelayQueue添加5个任务(AE),具有各种延迟(0ms,10ms,100ms 1000ms,10000ms)
  2. 启动另一个步骤,在3000ms后向DelayQueue添加另一个任务
  3. 主线程轮询DelayQueue并报告每个任务到期
  4. 在8000ms之后,主线程报告DelayQueue中剩余的任务

我从代码示例中获得的输出是:

------initial tasks ---------------
task A due in 0ms
task B due in 9ms
task C due in 99ms
task D due in 999ms
task E due in 9999ms
task F due in 99999ms
------processing--------------------
time = 5    task A due in -1ms
time = 14   task B due in 0ms
time = 104  task C due in 0ms
time = 1004 task D due in 0ms
time = 3003 added task Z due in 0ms
------remaining after 15007ms -----------
task F due in 84996ms
task E due in -5003ms
task Z due in -12004ms

我的问题是:为什么在15000ms之后,DelayQueue中还有剩余的任务(即GetDelay()返回-ve值的位置)?

我检查过的一些事情:

  • 我已经实现了compareTo()来定义Tasks的自然顺序
  • equals()与compareTo()一致
  • hashCode()已被覆盖

我将最感兴趣的是学习如何解决这个问题。 预先感谢您的帮助。 (以及帮助我​​约会的所有Stack Overflow答案:)

    package test;

    import java.util.concurrent.DelayQueue;
    import java.util.concurrent.Delayed;
    import java.util.concurrent.TimeUnit;

    public class Test10_DelayQueue {

       private static final TimeUnit delayUnit = TimeUnit.MILLISECONDS;
       private static final TimeUnit ripeUnit = TimeUnit.NANOSECONDS;

       static long startTime;

       static class Task implements Delayed {    
          public long ripe;
          public String name;    
          public Task(String name, int delay) {
             this.name = name;
             ripe = System.nanoTime() + ripeUnit.convert(delay, delayUnit);
          }

      @Override
      public boolean equals(Object obj) {
         if (obj instanceof Task) {
            return compareTo((Task) obj) == 0;
         }
         return false;
      }

      @Override
      public int hashCode() {
         int hash = 7;
         hash = 67 * hash + (int) (this.ripe ^ (this.ripe >>> 32));
         hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
         return hash;
      }

      @Override
      public int compareTo(Delayed delayed) {
         if (delayed instanceof Task) {
            Task that = (Task) delayed;
            return (int) (this.ripe - that.ripe);
         }
         throw new UnsupportedOperationException();
      }

      @Override
      public long getDelay(TimeUnit unit) {
         return unit.convert(ripe - System.nanoTime(), ripeUnit);
      }

      @Override
      public String toString() {
         return "task " + name + " due in " + String.valueOf(getDelay(delayUnit) + "ms");
          }
       }

       static class TaskAdder implements Runnable {

      DelayQueue dq;
      int delay;

      public TaskAdder(DelayQueue dq, int delay) {
         this.dq = dq;
         this.delay = delay;
      }

      @Override
      public void run() {
         try {
            Thread.sleep(delay);

            Task z = new Task("Z", 0);
            dq.add(z);

            Long elapsed = System.currentTimeMillis() - startTime;

            System.out.println("time = " + elapsed + "\tadded " + z);

         } catch (InterruptedException e) {
         }
      }
    }

    public static void main(String[] args) {
      startTime = System.currentTimeMillis();
      DelayQueue<Task> taskQ = new DelayQueue<Task>();

      Thread thread = new Thread(new TaskAdder(taskQ, 3000));
      thread.start();

      taskQ.add(new Task("A", 0));
      taskQ.add(new Task("B", 10));
      taskQ.add(new Task("C", 100));
      taskQ.add(new Task("D", 1000));
      taskQ.add(new Task("E", 10000));
      taskQ.add(new Task("F", 100000));

      System.out.println("------initial tasks ---------------");
      Task[] tasks = taskQ.toArray(new Task[0]);
      for (int i = 0; i < tasks.length; i++) {
         System.out.println(tasks[i]);
      }

      System.out.println("------processing--------------------");
      try {
         Long elapsed = System.currentTimeMillis() - startTime;
         while (elapsed < 15000) {
            Task task = taskQ.poll(1, TimeUnit.SECONDS);
            elapsed = System.currentTimeMillis() - startTime;
            if (task != null) {
               System.out.println("time = " + elapsed + "\t" + task);
            }
         }

         System.out.println("------remaining after " + elapsed + "ms -----------");
         tasks = taskQ.toArray(new Task[0]);
         for (int i = 0; i < tasks.length; i++) {
            System.out.println(tasks[i]);
         }

      } catch (InterruptedException e) {
      }
    }
    }

The java code sample below uses a java DelayQueue to process tasks. However the insertion of a task from another thread appears to disrupt (my) expected behaviour.

Apologies that the code example is so long, but in summary:

  1. The main thread adds 5 tasks (A-E) to a DelayQueue with various delays (0ms, 10ms, 100ms 1000ms, 10000ms)
  2. Another tread is started which adds another task to the DelayQueue after 3000ms
  3. The main thread polls the DelayQueue and reports as each Task expires
  4. After 8000ms the main thread reports the Tasks remaining in the DelayQueue

The output that I get from the code sample is:

------initial tasks ---------------
task A due in 0ms
task B due in 9ms
task C due in 99ms
task D due in 999ms
task E due in 9999ms
task F due in 99999ms
------processing--------------------
time = 5    task A due in -1ms
time = 14   task B due in 0ms
time = 104  task C due in 0ms
time = 1004 task D due in 0ms
time = 3003 added task Z due in 0ms
------remaining after 15007ms -----------
task F due in 84996ms
task E due in -5003ms
task Z due in -12004ms

My question is: why after 15000ms are there expired Tasks remaining in the DelayQueue (ie where GetDelay() returns a -ve value)?

Some things that I have checked:

  • I have implemented compareTo() to define the natural order of Tasks
  • equals() is consistent with compareTo()
  • hashCode() has been overridden

I will be most interested to learn how to resolve this problem. Thank you in advance for your assistance. (and for all of those Stack Overflow answers that have helped me to date :)

    package test;

    import java.util.concurrent.DelayQueue;
    import java.util.concurrent.Delayed;
    import java.util.concurrent.TimeUnit;

    public class Test10_DelayQueue {

       private static final TimeUnit delayUnit = TimeUnit.MILLISECONDS;
       private static final TimeUnit ripeUnit = TimeUnit.NANOSECONDS;

       static long startTime;

       static class Task implements Delayed {    
          public long ripe;
          public String name;    
          public Task(String name, int delay) {
             this.name = name;
             ripe = System.nanoTime() + ripeUnit.convert(delay, delayUnit);
          }

      @Override
      public boolean equals(Object obj) {
         if (obj instanceof Task) {
            return compareTo((Task) obj) == 0;
         }
         return false;
      }

      @Override
      public int hashCode() {
         int hash = 7;
         hash = 67 * hash + (int) (this.ripe ^ (this.ripe >>> 32));
         hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
         return hash;
      }

      @Override
      public int compareTo(Delayed delayed) {
         if (delayed instanceof Task) {
            Task that = (Task) delayed;
            return (int) (this.ripe - that.ripe);
         }
         throw new UnsupportedOperationException();
      }

      @Override
      public long getDelay(TimeUnit unit) {
         return unit.convert(ripe - System.nanoTime(), ripeUnit);
      }

      @Override
      public String toString() {
         return "task " + name + " due in " + String.valueOf(getDelay(delayUnit) + "ms");
          }
       }

       static class TaskAdder implements Runnable {

      DelayQueue dq;
      int delay;

      public TaskAdder(DelayQueue dq, int delay) {
         this.dq = dq;
         this.delay = delay;
      }

      @Override
      public void run() {
         try {
            Thread.sleep(delay);

            Task z = new Task("Z", 0);
            dq.add(z);

            Long elapsed = System.currentTimeMillis() - startTime;

            System.out.println("time = " + elapsed + "\tadded " + z);

         } catch (InterruptedException e) {
         }
      }
    }

    public static void main(String[] args) {
      startTime = System.currentTimeMillis();
      DelayQueue<Task> taskQ = new DelayQueue<Task>();

      Thread thread = new Thread(new TaskAdder(taskQ, 3000));
      thread.start();

      taskQ.add(new Task("A", 0));
      taskQ.add(new Task("B", 10));
      taskQ.add(new Task("C", 100));
      taskQ.add(new Task("D", 1000));
      taskQ.add(new Task("E", 10000));
      taskQ.add(new Task("F", 100000));

      System.out.println("------initial tasks ---------------");
      Task[] tasks = taskQ.toArray(new Task[0]);
      for (int i = 0; i < tasks.length; i++) {
         System.out.println(tasks[i]);
      }

      System.out.println("------processing--------------------");
      try {
         Long elapsed = System.currentTimeMillis() - startTime;
         while (elapsed < 15000) {
            Task task = taskQ.poll(1, TimeUnit.SECONDS);
            elapsed = System.currentTimeMillis() - startTime;
            if (task != null) {
               System.out.println("time = " + elapsed + "\t" + task);
            }
         }

         System.out.println("------remaining after " + elapsed + "ms -----------");
         tasks = taskQ.toArray(new Task[0]);
         for (int i = 0; i < tasks.length; i++) {
            System.out.println(tasks[i]);
         }

      } catch (InterruptedException e) {
      }
    }
    }

原文:https://stackoverflow.com/questions/12142025
更新时间:2023-05-24 18:05

最满意答案

嗨,现在你可以尝试专注模糊

$( "#service" ).focus(function() {
  $('#service').css({ 'width': '134%' });
});

$( "#service" ).blur(function() {
  $('#service').css({ 'width': '100%' });
});

演示


Hi now you can try to focus and blur

$( "#service" ).focus(function() {
  $('#service').css({ 'width': '134%' });
});

$( "#service" ).blur(function() {
  $('#service').css({ 'width': '100%' });
});

Demo

相关问答

更多
  • 您可以使用generic on处理程序手动绑定到keydown事件。 Elm目前不支持开箱即用的onKeyDown处理程序 - 但它们将在未来进行规划。 它看起来像是从event.keyCode移向event.key。 一旦这在更多浏览器中得到支持,我们可以在这里为onKeyUp,onKeyDown,onKeyPress等添加助手( 源代码 ) 在此之前,您可以简单编写自己的处理程序并使用键码13(输入)来执行您的操作。 将以下代码复制到elm-lang.org/try或打开https://runelm.i ...
  • 这可以通过在HTML中使用placeholder属性来完成。 例: 对于原生不支持此属性的浏览器,您可以使用JavaScript。 如果你使用jQuery,你可以考虑使用我的占位符插件jQuery ,这是我见过的最强大的解决方案。 这是一个演示页面: http : //mathiasbynens.be/demo/placeholder This can be done by using the placehol ...
  • 您可以使用change事件; $( "#EmailAddress" ).change(function() { $("#Username").val(this.value); }); You could use change event; $( "#EmailAddress" ).change(function() { $("#Username").val(this.value); });
  • 为什么不改变你的代码来切换一个类,从而保持功能(JS)和样式(CSS)之间的清晰分离, 以下是一些示例代码,您可能需要根据自己的确切需求进行编辑。 演示小提琴 JS $('.icon').click(function() { $('.search').toggleClass('expanded'); }); CSS .box { position: relative; width: 220px; } .search { width: 200px; max-widt ...
  • 刚刚使用DevExpress VCL 13.2对其进行测试,无需编码即可轻松完成(如果我理解您想要实现的目标)。 基本上,您需要设置以下属性: 将Memo分配给列的Properties ,并确保其WantReturns属性设置为true。 在TableView将OptionsView.CellAutoHeight属性设置为true。 同样在TableView ,根据需要将OptionsBehavior.EditAutoHeight设置为eahEditor (编辑器垂直大小以适合内容)或eahRow (编辑时 ...
  • 嗨,现在你可以尝试专注和模糊 $( "#service" ).focus(function() { $('#service').css({ 'width': '134%' }); }); $( "#service" ).blur(function() { $('#service').css({ 'width': '100%' }); }); 演示 Hi now you can try to focus and blur $( "#service" ).focus(function() { $ ...
  • 您必须从onsubmit处理程序返回false才能取消默认操作。 但我可能会稍微清理你的代码并不引人注意地订阅提交事件:
    Create Desination
  • 如果您只想将所有输入字段更改为本机文本: