В коде, над которым я работаю, есть несколько мест, где я делаю что-то вроде этого:
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 получил прерывание во время операции дискового ввода-вывода, проверьте свое приложение на источник прерывания»). , и все последующие коммуникации с базой данных превращаются в ужасный беспорядок. Есть ли какой-нибудь удобный способ защитить поток от прерывания, когда он не ожидает в очереди блокировки, или, альтернативно, нацелить прерывание на очередь блокировки?
Два решения, которые я видел или которые мне приходили в голову, - это вставить объект «ядовитая таблетка» в очередь, чтобы закрыть его, и иметь дополнительное поле boolean interruptsWelcome
, которое можно было бы проверить с помощью метода stop()
, но ни одно из них не особенно привлекательно. для меня - мне пришлось бы либо возиться с иерархией классов (Foo
- нетривиальный класс), либо создавать массу кода синхронизации. Есть что-нибудь поприличнее?