77 static void test(boolean notify, boolean interrupt, int... timeouts) throws Exception {
78 try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
79 for (int timeout : timeouts) {
80 var queue = new SynchronousQueue<Thread>();
81 var lock = new Object();
82
83 // virtual thread waits with Object.wait(timeout)
84 executor.submit(() -> {
85 queue.put(Thread.currentThread());
86 synchronized (lock) {
87 lock.wait(timeout);
88 }
89 return null;
90 });
91
92 // wait for thread to start
93 Thread thread = queue.take();
94
95 // start thread to Object.notifyAll at around time that the timeout expires
96 if (notify) {
97 if (ThreadLocalRandom.current().nextBoolean()) {
98 synchronized (lock) {
99 sleepLessThan(timeout);
100 lock.notifyAll();
101 }
102 } else {
103 sleepLessThan(timeout);
104 synchronized (lock) {
105 lock.notifyAll();
106 }
107 }
108 }
109
110 // start thread to interrupt first thread at around time that the timeout expires
111 if (interrupt) {
112 executor.submit(() -> {
113 sleepLessThan(timeout);
114 thread.interrupt();
115 return null;
116 });
117 }
118 }
119 }
120 }
121
122 /**
123 * Sleeps for just less than the given timeout, in millis.
124 */
125 private static void sleepLessThan(long timeout) throws InterruptedException {
126 int delta = ThreadLocalRandom.current().nextInt(10);
127 Thread.sleep(timeout - delta);
|
77 static void test(boolean notify, boolean interrupt, int... timeouts) throws Exception {
78 try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
79 for (int timeout : timeouts) {
80 var queue = new SynchronousQueue<Thread>();
81 var lock = new Object();
82
83 // virtual thread waits with Object.wait(timeout)
84 executor.submit(() -> {
85 queue.put(Thread.currentThread());
86 synchronized (lock) {
87 lock.wait(timeout);
88 }
89 return null;
90 });
91
92 // wait for thread to start
93 Thread thread = queue.take();
94
95 // start thread to Object.notifyAll at around time that the timeout expires
96 if (notify) {
97 executor.submit(() -> {
98 if (ThreadLocalRandom.current().nextBoolean()) {
99 synchronized (lock) {
100 sleepLessThan(timeout);
101 lock.notifyAll();
102 }
103 } else {
104 sleepLessThan(timeout);
105 synchronized (lock) {
106 lock.notifyAll();
107 }
108 }
109 return null;
110 });
111 }
112
113 // start thread to interrupt first thread at around time that the timeout expires
114 if (interrupt) {
115 executor.submit(() -> {
116 sleepLessThan(timeout);
117 thread.interrupt();
118 return null;
119 });
120 }
121 }
122 }
123 }
124
125 /**
126 * Sleeps for just less than the given timeout, in millis.
127 */
128 private static void sleepLessThan(long timeout) throws InterruptedException {
129 int delta = ThreadLocalRandom.current().nextInt(10);
130 Thread.sleep(timeout - delta);
|