0

I want to have 3 threads doing a task concurrently and also I want a thread that do a scheduled task over a period of time (runs every 10 secs). But I want when the 3 threads finish to run only once the scheduled task and then I want this thread to terminate. What is the best way to implement these threads? Is the ExecutorService Interface suitable for this.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Manos
  • 151
  • 2
  • 12

2 Answers2

3

Here an example that I've just written:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Example {

    public static void main(String[] args) throws InterruptedException {
        ScheduledFuture future = Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new MyScheduledTask(), 0, 10, TimeUnit.SECONDS);
        ExecutorService executor = Executors.newFixedThreadPool(3); // pool composed of 3 threads
        for (int i = 0; i < 3; i++) {
            // for the example assuming that the 3 threads execute the same task.
            executor.execute(new AnyTask()); 
        }
        // This will make the executor accept no new threads
        // and finish all existing threads in the queue
        executor.shutdown();
        // expect current thread to wait for the ending of the 3 threads
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.TimeUnit.NANOSECONDS); 
        future.cancel(false); // to exit properly the scheduled task
        // reprocessing the scheduled task only one time as expected
        new Thread(new ScheduledTask()).start(); 

    }


}

class MyScheduledTask implements Runnable {
    @Override
    public void run() {
        //Process scheduled task here
    }
}

class AnyTask implements Runnable {
    @Override
    public void run() {
        //Process job of threads here
    }
}
Mik378
  • 21,881
  • 15
  • 82
  • 180
  • It works. Actually the problem with my solution was that I put the `sheduler.shutdown()` inside the try block of the `executor.aWaitTermination()`. I used a `ScheduledExecutorService` to create the scheduler. What do you think about that solution? – Manos Oct 24 '12 at 02:04
  • @Manos Samatas hmm may you show your code by updating your post? – Mik378 Oct 24 '12 at 02:05
  • @Manos Samatas Anyway, `executor.aWaitTermination()` must logically be placed after `sheduler.shutdown()` otherwise the current thread would wait for the maximum amount of time and then pool would shutdown...Just imagine the decrease of performance. Moreover, nothing would prevent current thread to continue its task before waiting for termination of other jobs the 3 threads. – Mik378 Oct 24 '12 at 02:14
  • @Mik378 the task should run every 10 sec so it should be `scheduleAtFixedRate(new MyScheduledTask(), 10, 10, TimeUnit.SECONDS)` . How would you adjust the `future.cancel()` and `executors.shutdown()` in this situation ? – clinton Oct 24 '12 at 05:44
  • `scheduler.schedule(new Runnable() { public void run() { future.cancel(true); } }, 60 * 60, TimeUnit.SECONDS);` Ok I answered my own question. A reference to the scheduled future and scheduler is needed to send an interrupt to the task. – clinton Oct 24 '12 at 05:54
1

Here is an example of a Periodic Task Scheduler which executes tasks one after the other. The task scheduler takes an array of tasks and terminates each task after a specified interval in a separate thread. After 20 seconds the main thread shutsdown the scheduler and stops all waiting tasks.

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Example {

    class ScheduledRepeatingTask implements Runnable {
        final ScheduledExecutorService scheduler = Executors
                .newScheduledThreadPool(1);

        List<Runnable> taskCollection;
        Iterator<Runnable> taskIterator;

        Runnable getCancelRunnable(final ScheduledFuture<?> future) {

            Runnable cancelFuture = new Runnable() {
                public void run() {
                    future.cancel(true);
                }
            };
            return cancelFuture;
        }

        public ScheduledRepeatingTask(Runnable[] tasks) {
            super();
            taskCollection = Arrays.asList(tasks);
            taskIterator = taskCollection.iterator();
        }

        public void shutdownScheduler() throws InterruptedException {
            scheduler.shutdown();
            boolean execTerminated = scheduler.awaitTermination(5,
                    TimeUnit.SECONDS);

            if (!execTerminated) {
                scheduler.shutdownNow();
            }
        }

        public boolean isShutdown(){            
            return scheduler.isShutdown();
        }

        public void scheduleRepeatingTask(ScheduledFuture<?> future,
                ScheduledFuture<?> futureCancel) {

            try {
                futureCancel.get();
                future.get();

            } catch (CancellationException e) {
                System.out.println("cancelled.");
            } catch (ExecutionException e) {
                Throwable exp = e.getCause();
                if (exp instanceof RuntimeException) {
                    System.out.println("failed.");
                    RuntimeException rt = (RuntimeException) exp;
                    throw rt;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                if (!scheduler.isShutdown() && taskIterator.hasNext()) {
                    future = scheduler.scheduleAtFixedRate(taskIterator.next(),
                            2, 2, TimeUnit.SECONDS);
                    futureCancel = scheduler.schedule(
                            getCancelRunnable(future), 5, TimeUnit.SECONDS);
                    scheduleRepeatingTask(future, futureCancel);

                }
            }
        }

        @Override
        public void run() {
            if (!scheduler.isShutdown() && taskIterator.hasNext()) {
                ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(
                        taskIterator.next(), 2, 2, TimeUnit.SECONDS);
                ScheduledFuture<?> futureCancel = scheduler.schedule(
                        getCancelRunnable(future), 5, TimeUnit.SECONDS);
                scheduleRepeatingTask(future, futureCancel);
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        Example example = new Example();
        ExecutorService executor = Executors.newCachedThreadPool(); 

        Runnable[] tasks = { new Task1(), new Task2(), new Task1() };

        ScheduledRepeatingTask scheduledRepeatingTask = example.new ScheduledRepeatingTask(tasks);

        executor.execute(scheduledRepeatingTask);

        Thread.sleep(20000);

        scheduledRepeatingTask.shutdownScheduler();

        executor.shutdown();

    }

}

class Task1 implements Runnable {
    @Override
    public void run() {
        System.out.println("Task 1");
    }
}

class Task2 implements Runnable {
    @Override
    public void run() {
        System.out.println("Task 2");
    }
}
clinton
  • 612
  • 3
  • 6