سؤال

I have a ThreadPoolExecutor:

ThreadPoolExecutor service = new ThreadPoolExecutor(N_THREADS, N_THREADS, 0L, TimeUnit.MILLISECONDS, blockingQueue, rejectedExecutionHandler);

The service executes threads implementing the Runnable interface. Each thread processes a file on disk. I found that after several hours, two threads (or cores depending on what htop shows in Linux) were running and had been running for 13 hours. What's even worse is that the remaining cores showed no activity as if they were waiting for the two threads to complete.

Questions: 1 - I have read a lot on how this problem may be resolved but nothing conclusive. As far as I can work out, you CANNOT stop a Runnable using the ThreadPoolExecutor because it is an independent thread that just runs. Using the Future framework:

Future<?> f = f.get(submittedtask,XX)

allows you to set a timeout and fetch the future result, but get blocks all the threads effectively making the implementation serial. Is it possible to interrupt a Runnable after a given time using the threadpoolexecutor, get the thread back to the pool so it can pickup a new task and carry on.

2 - My big concern is why, using htop, I see two threads/cores running and no other core/thread are running despite many tasks are still waiting to execute (i.e. there are many files left to process). Any insight?

هل كانت مفيدة؟

المحلول

You could create a second scheduled thread pool to which you would submit cancellation tasks for each of the returned Futures. Each of these tasks after a given timeout would check if it's associated Future is done and if not, cancel it. Cancellation would trigger thread interruption, so you might need to support it in your tasks by checking the interrupted flag: Thread.interrupted().

The size of this second thread pool could be minimal, i.e. 1 as this job takes minimum of CPU time.

Code example:

ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

...

while(...){
    final Future<?> f = pool.submit(...);

    service.schedule(new Runnable() {
        @Override
        public void run() {
            if(!f.isDone()){
                f.cancel(true);
            }
        }
    }, 1, TimeUnit.MINUTES);
}

service.awaitTermination(1, TimeUnit.MINUTES);
service.shutdown();

نصائح أخرى

You can tell a thread that you wish to interrupt:

An interrupt is an indication to a thread that it should stop what it is doing and do something else.

You can interrupt your thread with Future.cancel(true). It's in your responsibility to implement the Runnable in a manner that it obeys that wish by checking its Thread.interrupted() state.

In order to see details about process thread run:

ps -eLf | grep <PROCESS_PID> 

Since htop shows you the running processes list, where each process has at least one thread.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top