In some code I’m working on, there are a couple of places where I do something like this:
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();
}
}
This, however, is causing problems as the thread is sometimes interrupted when it is in the insertIntoDatabase() method. As we’re using Apache Derby, it throws a hissy fit (to wit: “java.sql.SQLException: Derby thread received an interrupt during a disk I/O operation, please check your application for the source of the interrupt.”), and all subsequent database communication falls down in a nasty mess. Is there any tidy way to protect the thread from an interrupt when it’s not waiting on the blocking queue, or alternatively to target the interrupt at the blocking queue?
Two solutions that I have seen suggested or have occurred to me are to insert a “poison pill” object into the queue to shut it down, and to have an extra boolean interruptsWelcome field that could be checked by the stop() method, but neither is particularly attractive to me – I’d either have to mess with the class hierarchy (Foo is not a trivial class) or produce masses of synchronisation code. Is there something neater?
The first thing you may want to do is to use an ExecutorService. In which you can use a single thread to submit the foo requests.
Your runnable itself can just ignore interrupted exception if you want
Edit:
I saw your comment on the other answer and to answer that question in terms of using an ExecutorService. By having a singleThreadExeuctor you are restricting to one upload via thread-confinement. If only one thread is running within the service only one runnable will run at a time. The others will just queue up until the previous finished.