Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a fixed rate poller with ScheduledExecutorService?

Given the following class:

public class Poller implements Runnable {
    public static final int CORE_POOL_SIZE = 4;

    public boolean running;
    public ScheduledExecutorService ses;

    public void startPolling() {
        this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE);
        this.ses.scheduleAtFixedRate(this, 0, 1, TimeUnit.SECONDS);
    }

    public void run() {
        running = true;
        // ... Do something ...
        running = false;
    }
}

The ScheduledExecutorService has a core thread pool size of 4 but will more than one poller thread ever be created? Since this is passed into scheduleAtFixedRate does that mean there will only ever be one thread - or does something more complex happen behind the scenes?

And 2 bonus questions:-

  1. Should running be static?
  2. Is CORE_POOL_SIZE redundant?
like image 606
Steve Chambers Avatar asked Feb 18 '23 04:02

Steve Chambers


2 Answers

The ScheduledExecutorService has a core thread pool size of 4 but will more than one poller thread ever be created?

It depends - if you run your program long enough, it will probably create 4 threads. If you quit after running your scheduled task only once or twice, you might only see 2 or 3 threads.

Why does it matter?

One way to monitor thread creation is to provide your own ThreadFactory:

this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE, new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                System.out.println("Creating thread");
                return new Thread(r);
            }
        }); 

Should running be static?

It depends on what you want to achieve... Since you are not really it using in your example it is hard to say. You might need to make it static if you have several instances of Poller and you want them to not run concurrently for example.

Whether it is static or not, if you use it as a flag, you should make it volatile to ensure visibility.

Is CORE_POOL_SIZE redundant?

Not sure what you mean. It is a mandatory parameter so you need to provide a value. If you know for sure that no two execution will run concurrently, you could only have one thread. That will also prevent concurrent execution (so if one scheduled task needs to start but another is already running, the new one will be delayed).

like image 152
assylias Avatar answered Feb 20 '23 10:02

assylias


scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)

This method schedules a task to be executed periodically. The task is executed the first time after the initialDelay, and then recurringly every time the period expires.

If any execution of the given task throws an exception, the task is no longer executed. If no exceptions are thrown, the task will continue to be executed until the ScheduledExecutorService is shut down.

If a task takes longer to execute than the period between its scheduled executions, the next execution will start after the current execution finishes. The scheduled task will not be executed by more than one thread at a time.

like image 40
Abhishek Kumar Avatar answered Feb 20 '23 11:02

Abhishek Kumar