user2960779
user2960779

Reputation: 11

Executors Factory method newScheduledThreadPool always returns the same Thread pool

As per the Java Specifications: public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) "Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically."

But from my experience even if I create two seperate ScheduledExecutorService calling the newScheduledThreadPool(int corePoolSize) factory method twice and schedule two completely different Callable tasks, both the threads run synchonously i.e. one waits on the other. Considering two seperate thread pools have been created, they shoud have run simultaneously.

public static ScheduledExecutorService SCANNER_SERVICE = Executors.newScheduledThreadPool(10);
public static ScheduledExecutorService UNSERVICERESTORED_SCANNER_SERVICE = Executors.newScheduledThreadPool(10);

Scanner scanner=new Scanner();
UnServiceRestoredTicketScanner unServiceRestoredTicketScanner=new UnServiceRestoredTicketScanner();

if(SCANNER_SERVICE.isShutdown())
    SCANNER_SERVICE=Executors.newScheduledThreadPool(10);
SCANNER_SERVICE.scheduleWithFixedDelay(scanner, 0, 30, TimeUnit.SECONDS);


if(UNSERVICERESTORED_SCANNER_SERVICE.isShutdown())
    UNSERVICERESTORED_SCANNER_SERVICE=Executors.newScheduledThreadPool(10);
UNSERVICERESTORED_SCANNER_SERVICE.scheduleWithFixedDelay(unServiceRestoredTicketScanner, 0, 40, TimeUnit.SECONDS);

Output:

Scanner Thread started - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18
ServiceRestoredTicketScanner Thread started - com.csp.productionsupport.queuemonitor.events.UnServiceRestoredTicketScanner@15ed659
Thread ended - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18
Scanner Thread started - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18
ServiceRestoredTicketScanner Thread ended - com.csp.productionsupport.queuemonitor.events.UnServiceRestoredTicketScanner@15ed659
Thread ended - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18
Scanner Thread started - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18
ServiceRestoredTicketScanner Thread started - com.csp.productionsupport.queuemonitor.events.UnServiceRestoredTicketScanner@15ed659
Thread ended - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18
Scanner Thread started - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18
ServiceRestoredTicketScanner Thread ended - com.csp.productionsupport.queuemonitor.events.UnServiceRestoredTicketScanner@15ed659
Thread ended - com.csp.productionsupport.queuemonitor.events.Scanner@1fa6d18

Upvotes: 1

Views: 2812

Answers (2)

user2960779
user2960779

Reputation: 11

Here is this scenerio:

public class ThreadA implements Runnable{

@Override
public void run() {
    // TODO Auto-generated method stub
    Date startTime =new Date();
    System.out.println("Thread A started at - "+startTime);
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    Date endTime =new Date();
    System.out.println("Thread A ended at - "+endTime);
    System.out.println("Time taken by Thread A - "+(endTime.getTime()-startTime.getTime())+"ms");

}}

public class ThreadB implements Runnable {

@Override
public void run() {
    // TODO Auto-generated method stub
    Date startTime = new Date();
    System.out.println("Thread B started at - " + startTime);
    try {
        Thread.sleep(60000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    Date endTime = new Date();
    System.out.println("Thread B ended at - " + endTime);
    System.out.println("Time taken by Thread B - "+ (endTime.getTime() - startTime.getTime()) + "ms");
}}

public class ExecutorTest {

public static ScheduledExecutorService EXECUTOR_A = Executors.newScheduledThreadPool(10);
public static ScheduledExecutorService EXECUTOR_B = Executors.newScheduledThreadPool(10);

public static void main(String[] args) {
    ThreadA threadA=new ThreadA();
    ThreadB threadB=new ThreadB();

    if(EXECUTOR_A.isShutdown())
        EXECUTOR_A=Executors.newScheduledThreadPool(10);
    EXECUTOR_A.scheduleWithFixedDelay(threadA, 0, 30, TimeUnit.SECONDS);

    if(EXECUTOR_B.isShutdown())
        EXECUTOR_B=Executors.newScheduledThreadPool(10);
    EXECUTOR_B.scheduleWithFixedDelay(threadB, 0, 40, TimeUnit.SECONDS);
}}

Output:

Thread A started at - Thu Nov 07 12:22:12 IST 2013
Thread B started at - Thu Nov 07 12:22:12 IST 2013
Thread A ended at - Thu Nov 07 12:22:16 IST 2013
Time taken by Thread A - 4025ms
Thread A started at - Thu Nov 07 12:22:46 IST 2013
Thread A ended at - Thu Nov 07 12:22:50 IST 2013
Time taken by Thread A - 4010ms
Thread B ended at - Thu Nov 07 12:23:12 IST 2013
Time taken by Thread B - 59996ms
Thread A started at - Thu Nov 07 12:23:20 IST 2013
Thread A ended at - Thu Nov 07 12:23:24 IST 2013
Time taken by Thread A - 4010ms

Perfect output as designed. This is my scenerio but works perfectly here. Will recheck my code again.

Upvotes: 0

TwoThe
TwoThe

Reputation: 14269

There are a lot of things wrong with your code and your understanding of how things work.

First - as mentioned already in the comment - you are using the same scanner instance in both pools. This explains why you only get output from "one" thread.

Since you schedule these threads for each 30/40 seconds, they will not run in parallel for the first 3-4 runs each:

30s: Thread A
40s: Thread B
60s: Thread A
80s: Thread B
90s: Thread A
120s: Thread A + B (it will be "random" which one runs first)

There is a misunderstanding of the concept Thread. It doesn't matter if you have 2 pools with 10 threads each, or 1 pool with 20 threads. In your example it wouldn't even make a difference if you have only 1 pool with 1 threads. The only reason to use more than one pool is to manage those pools differently and not to have threads inside run "separately". Therefore, to answer your actual question, it doesn't matter how Java manages those pools internally.

I don't know the rest of your code, but the fact that you check if a pool is shut down and then create a new one, tells me that there is an architectural issue in your code at a whole. Shutting down a pool is only necessary if all work is done and the main thread needs to wait for all threads to finish to either process the data or exit. It is especially pointless to use a thread pool to save the overhead cost of thread creation and then create the pool over and over again.

There is too little information on what you are trying to archive to give any further suggestions, but I am pretty sure that whatever you are trying to do, it is possible to do this a lot simpler than the way you presented. It might be helpful if you repost for an architectural help instead.

Upvotes: 4

Related Questions