在我正在编写的一些代码中,有几个地方我做了这样的事情:
public MyThread extends Thread{
boolean finished = false;
BlockingQueue<Foo> blockingQueue new LinkedBlockingQueue<Foo>();
public void run(){
while(!finished || (finished && !blockingQueue.isEmpty())){
try{
Foo f = blockingQueue.take();
insertIntoDatabase(f);
}
catch(InterruptedException e){
}
}
}
public void insertThis(Foo f) throws InterruptedException{
blockingQueue.put(f);
}
public void stop(){
finished = true;
this.interrupt();
}
}
但是,这会导致问题,因为线程在 insertIntoDatabase()
方法中有时会被中断。当我们使用 Apache Derby 时,它会发出嘶嘶声(即:“java.sql.SQLException:Derby 线程在磁盘 I/O 操作期间收到中断,请检查您的应用程序以获取中断源。”) ,所有后续的数据库通信都会陷入困惑。当线程不在阻塞队列上等待时,是否有任何简洁的方法来保护线程免受中断,或者将中断定位在阻塞队列上?
我看到建议或想到的两个解决方案是在队列中插入一个“毒丸”对象以将其关闭,并有一个额外的 boolean 中断欢迎字段,该字段可以是通过 stop()
方法进行检查,但这对我来说都不是特别有吸引力 - 我要么必须弄乱类层次结构(Foo
不是一个简单的类),要么产生大量同步代码。有没有更简洁的东西?
最佳答案
您可能想做的第一件事是使用 ExecutorService。您可以在其中使用单个线程来提交 foo 请求。
class FooRunner{
ExecutorService service = Executors.newSingleThreadExecutor();
//where RunnableFoo extends Foo and implements Runnable
public void insertThis(RunnableFoo f) throws InterruptedException{ Run
service.submit(f);
}
public void stop(){
service.shutdown();
}
}
如果您愿意,您的可运行本身可以忽略中断的异常
class RunnableFoo extends Foo implements Runnable{
public void run(){
try{
insertIntoDatabase(this);
}catch(InterruptedException ex){
ex.printStackTrace();
}
}
}
编辑:
我看到您对其他答案的评论,并根据使用 ExecutorService 来回答该问题。通过使用 singleThreadExeuctor,您可以通过线程限制来限制一次上传。如果服务中只有一个线程正在运行,则一次只会运行一个可运行对象。其他人只会排队,直到前一个完成。
关于java - 条件线程中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4737870/