I'm trying to wrap my head around threads and I've thought of this particular case: A scheduled runnable which will poll data from somewhere and when there is no data to poll the thread should wait for a while and then start polling again.
This is an example code of what I was trying to accomplish
public class ThreadTest {
public static void main(String[] args) {
Object lock = new Object();
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(new Worker(lock), 100, 1000, TimeUnit.MILLISECONDS);
while(!scheduledFuture.isDone()) {
}
System.out.println("Main finished");
}
public static class Worker implements Runnable {
private final Object lock;
public Worker(Object lock) {
this.lock = lock;
}
@Override
public void run() {
long startMilis = 0;
try {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " Simulating work by sleeping for 3 seconds");
Thread.sleep(3000);
startMilis = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + " Work done. Initiating wait for 200ms");
// this is supposed to pause the thread and release the lock and then wake up the thread after 200ms
// however what it seems to do is it puts the thread in the waiting state but it does not wake up
// after 200ms and resume, instead it skips to the finally block and completes the scheduled future
// stopping any further threads to start... why?
wait(200);
// this pauses the thread, keeping the lock, and the thread finishes after sleep. Works as intended.
//Thread.sleep(200);
}
System.out.println(Thread.currentThread().getName() + " Done waiting. Exiting");
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
long endMilis = System.currentTimeMillis();
long difference = endMilis - startMilis;
System.out.println(Thread.currentThread().getName() + " Finally block reached after " + difference + "ms");
}
}
}
}
If you run this code as-is it will spawn a thread running the Worker
runnable, the runnable will sleep for 3 seconds simulating some long lasting work, then it will hit the wait(200)
call and the thread will immediately go to the finally block and exit and the ScheduledFuture
will complete.
Why is that? I thought that wait(milis)
could be used for low-power polling, having the thread release it's lock and wait for some time before running again but this is only causing me more confusion.
Can anyone elaborate?