条件线程中断 [英] Conditional thread interrupt

查看:104
本文介绍了条件线程中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我正在处理的某些代码中,有几个地方我会这样做:

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();
    }
}

但是,由于线程是有时在 insertIntoDatabase()方法中时会中断。当我们使用Apache Derby时,它会产生嘶嘶声(例如: java.sql.SQLException:Derby线程在磁盘I / O操作期间收到了中断,请检查您的应用程序以获取中断源。) ,并且所有后续的数据库通信陷入混乱。当线程不在阻塞队列中等待时,是否有任何整洁的方法来保护线程免受中断,或者将中断定位在阻塞队列中?

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?

两种解决方案我已经看到有人建议或想到要在队列中插入毒丸对象以将其关闭,并有一个额外的 boolean interruptsWelcome 字段,该字段可能是通过 stop()方法检查,但是对我来说都不是很吸引人-我要么不得不弄乱类的层次结构( Foo 不是一个简单的类)或产生大量的同步代码。

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?

推荐答案

您可能要做的第一件事是使用ExecutorService。在其中可以使用单个线程提交foo请求。

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.

    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();
        }

    }

您的可运行自身可以忽略被中断

Your runnable itself can just ignore interrupted exception if you want

class RunnableFoo extends Foo implements Runnable{

 public void run(){
     try{
         insertIntoDatabase(this);
     }catch(InterruptedException ex){
       ex.printStackTrace();
     }
 }
}

编辑:

我看到了您对另一个答案的评论,并就使用ExecutorService回答了该问题。通过使用singleThreadExeuctor,您将只能通过线程约束限制一次上传。如果服务中仅运行一个线程,则一次只能运行一个可运行线程。其他人将一直排队直到上一次完成。

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.

这篇关于条件线程中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆