Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread.interrupt is not called when using ExecutorService

I need MyThread.interrupt() to be called when I cancel currently executing task. Why isn't itpublic class Main {

public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    List<MyThread> threads = new ArrayList<Main.MyThread>();

    List<Future> futureList = new ArrayList<Future>();
    for (int i = 0; i < 30; i++) {
        MyThread myThread = new MyThread(i);
        futureList.add(executor.submit(myThread));
        threads.add(myThread);
    }
    for (Future future : futureList) {
        if (future != null) {
            future.cancel(true);
        }
    }

    // Calling interrupt directly. It works
    for (MyThread myThread : threads) {
        myThread.interrupt();
    }
    shutdownAndAwaitTermination(executor);

}

static void shutdownAndAwaitTermination(ExecutorService pool) {
    pool.shutdown(); // Disable new tasks from being submitted
    try {
        // Wait a while for existing tasks to terminate
        if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
            pool.shutdownNow(); // Cancel currently executing tasks
            // Wait a while for tasks to respond to being cancelled
            if (!pool.awaitTermination(10, TimeUnit.SECONDS)) System.err.println("Pool did not terminate");
            else System.out.println("Maybe OK");
        } else {
            System.out.println("OK");
        }
    } catch (InterruptedException ie) {
        // (Re-)Cancel if current thread also interrupted
        pool.shutdownNow();
        // Preserve interrupt status
        Thread.currentThread().interrupt();
    }
}

private static class MyThread extends Thread {

    HttpURLConnection connection;

    final int i;

    public MyThread(int i) {
        this.i = i;
    }

    @Override
    public void interrupt() {
        super.interrupt();
        if (connection != null) {
            connection.disconnect();
        }
    }

    @Override
    public void run() {
        // Initialize HttpURLConnection and upload / download data
    }

}

}

like image 830
Maksim Dmitriev Avatar asked Dec 26 '22 10:12

Maksim Dmitriev


2 Answers

It is called, change it here and see output

...
            } catch (InterruptedException e) {
                System.out.println(i + " interrupted");
                Thread.currentThread().interrupt();
            }
...

the problem is that ThreadPoolExecutor uses its own Thread to run your task and it will interrupt this thread not yours. It makes no sense to extend Thread, implement Runnable instead. If you still to use Thread then you can call MyThread.interrupt() directly from MyThread.run()

like image 134
Evgeniy Dorofeev Avatar answered Jan 05 '23 07:01

Evgeniy Dorofeev


executor.submit(new MyThread(i)) works because MyThread extends Thread which implements Runnable.

As such, the run method is actually executed by one of the 10 threads your started in the thread pool. When cancelling the Future, the interrupt method of MyThread is not executed as it is not the executing thread but considered a Runnable. Nevertheless, The interrupt of the threads started by your pool is called.

like image 31
Jean Logeart Avatar answered Jan 05 '23 06:01

Jean Logeart