import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class VirtualThreadSleepStarvationReproducer {

public static void main(String[] args) throws Exception {
System.setProperty("jdk.virtualThreadScheduler.parallelism", "3");

ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
for (int i = 0; i < 512; i++) {
executor.execute(new Sleep0Task());
}

executor.execute(new Sleep100Task());
Thread.sleep(Integer.MAX_VALUE);
}

private static class Sleep0Task implements Runnable {
private static final AtomicInteger threadIndex = new AtomicInteger(0);

@Override
public void run() {
Thread.currentThread().setName("virtual-thread-sleep0ms-" + threadIndex.getAndIncrement());
try {
while (true) {
Thread.sleep(0L);
}
} catch (Exception e) {
System.out.println("[ERROR] " + Thread.currentThread().getName() + " " + e.getMessage());
}
}
}

private static class Sleep100Task implements Runnable {
@Override
public void run() {
Thread.currentThread().setName("virtual-thread-sleep100ms");
try {
while (true) {
long begin = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + " start sleep");
Thread.sleep(100L);
System.out.println(Thread.currentThread().getName() + " sleep done, cost = " + (System.currentTimeMillis() - begin));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} 