-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
25.0.1
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
When performing sift-down operation, the moved "t' may not be a child of the target place, causing the min-heap structure being broken.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the test code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Tasks are executed in the ascending order of their respective delay, outputting the following content:
Delay 200
Delay 310
Delay 420
Delay 430
Delay 400
Delay 500
Delay 700
Delay 800
Delay 900
ACTUAL -
The output is as following. Note the 400-delayed task is executed after the 420 and 430 ones.
Delay 200
Delay 310
Delay 400
Delay 420
Delay 430
Delay 500
Delay 700
Delay 800
Delay 900
---------- BEGIN SOURCE ----------
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Application {
private static final long[] DELAYS = new long[] {400, 900, 800, 700, 600, 430, 420, 310, 500, 200};
private static final int DELAY_OFFSET = 5000;
private static final CountDownLatch LATCH = new CountDownLatch(DELAYS.length);
public static void main(String[] args) throws Exception {
ScheduledFuture<?>[] tasks = new ScheduledFuture[DELAYS.length];
ForkJoinPool pool = ForkJoinPool.commonPool();
for (int i = 0; i < DELAYS.length; ++i) {
TestRunnable runnable = new TestRunnable(DELAYS[i]);
tasks[i] = pool.schedule(runnable, runnable.delay + DELAY_OFFSET, TimeUnit.MILLISECONDS);
}
Thread.sleep(50);
tasks[4].cancel(true);
LATCH.countDown();
LATCH.await();
}
private static class TestRunnable implements Runnable {
private final long delay;
public TestRunnable(long delay) {
this.delay = delay;
}
@Override
public void run() {
synchronized (TestRunnable.class) {
System.out.println("Delay " + delay);
}
LATCH.countDown();
}
@Override
public String toString() {
return "toString called for delay " + delay;
}
}
}
---------- END SOURCE ----------
When performing sift-down operation, the moved "t' may not be a child of the target place, causing the min-heap structure being broken.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the test code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Tasks are executed in the ascending order of their respective delay, outputting the following content:
Delay 200
Delay 310
Delay 420
Delay 430
Delay 400
Delay 500
Delay 700
Delay 800
Delay 900
ACTUAL -
The output is as following. Note the 400-delayed task is executed after the 420 and 430 ones.
Delay 200
Delay 310
Delay 400
Delay 420
Delay 430
Delay 500
Delay 700
Delay 800
Delay 900
---------- BEGIN SOURCE ----------
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Application {
private static final long[] DELAYS = new long[] {400, 900, 800, 700, 600, 430, 420, 310, 500, 200};
private static final int DELAY_OFFSET = 5000;
private static final CountDownLatch LATCH = new CountDownLatch(DELAYS.length);
public static void main(String[] args) throws Exception {
ScheduledFuture<?>[] tasks = new ScheduledFuture[DELAYS.length];
ForkJoinPool pool = ForkJoinPool.commonPool();
for (int i = 0; i < DELAYS.length; ++i) {
TestRunnable runnable = new TestRunnable(DELAYS[i]);
tasks[i] = pool.schedule(runnable, runnable.delay + DELAY_OFFSET, TimeUnit.MILLISECONDS);
}
Thread.sleep(50);
tasks[4].cancel(true);
LATCH.countDown();
LATCH.await();
}
private static class TestRunnable implements Runnable {
private final long delay;
public TestRunnable(long delay) {
this.delay = delay;
}
@Override
public void run() {
synchronized (TestRunnable.class) {
System.out.println("Delay " + delay);
}
LATCH.countDown();
}
@Override
public String toString() {
return "toString called for delay " + delay;
}
}
}
---------- END SOURCE ----------