2

I've following code that puts some data into a blocking queue, and submits thread tasks to Java executor service based on a fixed thread pool. When I attempt to shutdown the executor though it doesn't shut down, any idea please?

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

public class ThreadExecutir {
    public static ArrayBlockingQueue<String> files;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        shutdownExec();
    }

    private static void shutdownExec() {
        int size = 10;
        files = new ArrayBlockingQueue<String>(100);
        for (int i = 0; i < 5; i++) {
            files.add("Java " + i);
        }

        ThreadExecutir outer = new ThreadExecutir();
        ExecutorService executor = Executors.newFixedThreadPool(size);
        for (int i = 0; i < 3 * size; i++) {
            executor.submit(outer.new myThread());
        }
        System.out.println(executor.isShutdown());
        executor.shutdown();

        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
            System.out.println("Awaiting for threads to complete!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (files.isEmpty())
            executor.shutdownNow();
        System.out.println(executor.isShutdown());

    }

    class myThread extends Thread {
        public void run() {

            String threadName = Thread.currentThread().getName();
            System.out.println("Thread " + threadName + "started running! ");
            try {
                String uploadThis = files.take();
                System.out.println("I'm working " + threadName + " "
                        + uploadThis);
                // this.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println("Thread " + threadName
                        + " finished running! ");
            }
        }
    }
}

2 Answers2

4

After a few myThread instances have consumed all the elements in files, the rest block on the files.take().

The javadoc of shutdown states

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.

You've submitted all your 30 tasks (10 of which are executing), before calling shutdown. So they all need to finish execution before the ExecutorService can be considered terminated. But most of them can't finish executing since nothing exists, at the moment, to get them to stop blocking at the take().

You need to either submit more items to the ArrayBlockingQueue or interrupt the threads in the ExecutorService. shutdownNow can be used to interrupt those threads.

Note that an interrupt might not be enough to stop your threads, since the interrupt might arrive before the blocking call. You'll need a more sophisticated solution, like a poison pill.


Although you've subclassed Thread,

class myThread extends Thread {

you're only using myThread as a Runnable (Thread implements Runnable). This is pretty pointless. Just implement Runnable

class myThread implements Runnable {
Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
1

You submitted only 5 strings into a queue and 30 tasks. First 5 tasks consume all 5 strings from files and next one is blocked trying to poll() string from empty queue (notEmpty.await() is called on the queue).

Thread will wait until it will be interrupted. Executor will wait until its threads are finished.

So the code will stuck on executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS) and never reach if (files.isEmpty()) executor.shutdownNow();

Looks like you have to use files.poll() instead of files.take() - it won't lock in empty queue return (count == 0) ? null : dequeue();.

Azee
  • 1,809
  • 17
  • 23