Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use Guava's AbstractExecutionThreadService for services that need to be interrupted?

I have a service that I would like to implement as a Google Guava Service.

The service basically runs a while (true) loop that processes events as they arrive on a BlockingQueue. Simplified sample code is available here:

https://gist.github.com/3354249

The problem is that the code blocks on BlockingQueue#take(), so the only way to stop the service is to interrupt its thread. Is this possible using Guava's AbstractExecutionThreadService?

Of course, in this case I could replace queue.take() with a polling loop using queue.poll(1, TimeUnit.SECONDS), thus removing the need for thread interruption. However:

  • I would like to avoid doing this, for both performance and code readability reasons

  • There are other cases where it is impossible to avoid thread interruption, e.g. if the service is blocked while reading bytes from an InputStream.

like image 995
Chris B Avatar asked Aug 15 '12 00:08

Chris B


1 Answers

You can override executor() method to supply your own executor, which will then store reference to the thread into your field. Then you can easily interrupt the thread, if needed.

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;

import com.google.common.util.concurrent.AbstractExecutionThreadService;

public abstract class InterruptibleExecutionThreadService extends AbstractExecutionThreadService {
    private final AtomicReference<Thread> runningThread = new AtomicReference<Thread>(null);

    @Override
    protected Executor executor() {
        return new Executor() {
            @Override
            public void execute(Runnable command) {
                Thread thread = Executors.defaultThreadFactory().newThread(command);
                runningThread.compareAndSet(null, thread);

                try {
                    thread.setName(serviceName());
                } catch (SecurityException e) {
                    // OK if we can't set the name in this environment.
                }
                thread.start();
            }
        };
    }

    protected void interruptRunningThread() {
        Thread thread = runningThread.get();
        if (thread != null) {
            thread.interrupt();
        }
    }
}
like image 110
Peter Štibraný Avatar answered Oct 19 '22 20:10

Peter Štibraný