Chr*_*s B 5 java service interrupt guava
我有一项服务,我想将其作为Google Guava实施Service.
该服务基本上运行一个while (true)循环,在事件到达时处理它们BlockingQueue.这里提供简化的示例代码:
https://gist.github.com/3354249
问题是代码阻塞BlockingQueue#take(),因此停止服务的唯一方法是中断其线程.这可能是使用番石榴的AbstractExecutionThreadService吗?
当然,在这种情况下,我可以queue.take()使用轮询循环替换queue.poll(1, TimeUnit.SECONDS),从而消除了线程中断的需要.然而:
出于性能和代码可读性的原因,我想避免这样做
在其他情况下,无法避免线程中断,例如,如果在从a读取字节时阻止服务InputStream.
您可以覆盖executor()方法以提供自己的执行程序,然后将执行程序存储到您的字段中.然后,如果需要,您可以轻松地中断线程.
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您想使用 an ,我认为中断线程并不是一个真正的选择AbstractExecutionThreadService,因为实际上没有任何方法可以获取对线程的引用来调用interrupt().
如果您使用的是 BlockingQueue,则必须在 while 循环内进行轮询以检查服务是否仍在运行,或者您可以使用哨兵值来提醒工作方法需要停止。
例子:
轮询:
while(isRunning()) {
Value v = queue.poll(1, TimeUnit.SECONDS);
// do something with v
}
Run Code Online (Sandbox Code Playgroud)
哨兵值:
while(isRunning()) {
Value v = queue.take();
if(v == POISON) {
break;
}
// do something with v
}
Run Code Online (Sandbox Code Playgroud)
我个人会尝试轮询解决方案,看看性能如何。您可能会惊讶于这对性能的影响如此之小。
至于从 InputStream 读取,如果 InputStream 寿命很长并且有可能无限期地阻塞,我认为使用 anAbstractExecutionThreadService是不可能的。您应该使用 anAbstractService它创建并保存对其自己的执行线程的引用,以便您可以在方法中中断它doStop()。