首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >条件线程中断

条件线程中断
EN

Stack Overflow用户
提问于 2011-01-20 00:28:19
回答 5查看 1.2K关注 0票数 2

在我正在编写的一些代码中,有几个地方我可以这样做:

代码语言:javascript
复制
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操作期间收到一个中断,请检查您的应用程序是否有中断的来源。“),所有后续的数据库通信都会陷入混乱。当线程不在阻塞队列中等待时,有没有什么好的方法来保护线程不受中断的影响,或者将中断定位在阻塞队列中?

我所看到或想到的两个解决方案是:将一个“毒丸”对象插入到队列中以关闭它,以及有一个可以由stop()方法检查的额外boolean interruptsWelcome字段,但这两个解决方案对我来说都不是特别有吸引力-我要么必须扰乱类层次结构(Foo不是一个微不足道的类),要么就必须生成大量的同步代码。有没有更整洁的东西?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-01-20 00:38:43

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

代码语言:javascript
复制
    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();
        }

    }

如果你愿意,你的runnable本身可以忽略中断的异常

代码语言:javascript
复制
class RunnableFoo extends Foo implements Runnable{

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

编辑:

我看到了你对另一个答案的评论,并从使用ExecutorService的角度回答了这个问题。通过使用singleThreadExeuctor,您可以通过线程限制将上传限制为一次。如果只有一个线程在服务中运行,那么一次只有一个runnable线程会运行。其他的只会排队,直到前一个完成。

票数 3
EN

Stack Overflow用户

发布于 2011-01-20 00:34:09

如果你想要的是在运行insertIntoDatabase()时不允许线程中断,那就去掉对这个方法的调用来分离Runnable,并将其提交给单独的Executor:

代码语言:javascript
复制
    while(!finished || (finished && !blockingQueue.isEmpty())){
        try{
            final Foo f = blockingQueue.take();

            executor.submit(new Runnable() {
                public void run() {
                    insertIntoDatabase(f);
                }
            });
        }
        catch(InterruptedException e){

        }
    }
票数 2
EN

Stack Overflow用户

发布于 2011-01-20 01:16:24

您可以放置前哨数值以停止处理。这不需要中断或复杂的检查。

代码语言:javascript
复制
public class MyThread extends Thread{
    static final Foo STOP = new Foo();
    final BlockingQueue<Foo> queue = new LinkedBlockingQueue<Foo>();

    public void run(){
        try{
           Foo f = queue.take();
           while(f != STOP) {
              insertIntoDatabase(f);
              f = queue.take();
           }
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void insertThis(Foo f) {
        queue.add(f); // never fills up.
    }

    public void stop() {
        queue.add(STOP);
    }
}

另一种方法可能是使用ExecutorService。

代码语言:javascript
复制
public class DatabaseWriter {
   final ExecutorService es = Executors.newSingleThreadExecutor();

   public void insertThis(final Foo f) {
       es.submit(new Runnable() {
           public void run() {
              insertIntoDatabase(f);
           }
       });
   }

   public void stop() {
       es.shutdown();
   }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4737870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档