【问题标题】:Java make sleeping threads do work in a thread poolJava使睡眠线程在线程池中工作
【发布时间】:2014-06-07 04:26:53
【问题描述】:

我有一个工作线程数固定的线程池(比如 4 个)。我不断地向执行者获取新的可运行文件。所有这些runnables都有一个长时间的睡眠调用,等待另一个线程被它中断:

Runnable runnable =  new Runnable() {
    @Override
    public void run() {
        //do preparation
        doPreWork();

        //wait for some other runnable to interrupt me
        try {
            Thread.sleep(40000);
        }
        catch(InterruptedException e) {
        }

        //finish work
        doAfterWork();
    }                   
}

所以问题是:当我将前 4 个可运行对象获取到我的执行程序时,所有工作线程都处于睡眠状态,而其他传入的可运行对象(其中很多,因为它们是不断传入的)排队并且必须等待可用线程。有什么办法,我可以使用睡眠线程来执行新传入的可运行对象,保持其他人的睡眠?

【问题讨论】:

  • 我不明白这个问题。如果您的任务调用睡眠,那么正在运行它的线程将无法执行任何其他操作。如果提交了另一个任务,它将启动另一个线程或等待,具体取决于正在使用的ExecutorService 的类型。
  • @Gray,问题是我不想为每个可运行的线程创建一个新线程,因为会有数千个线程。我该如何设计它,让排队的 runnbales 不用等待?
  • Thread.sleep() 在以下情况下很有用; (a) 你想强制一个特定的线程交错用于演示目的(例如,揭示一个并发错误),(b) 你想重新发明轮子,并编写你自己的调度程序,或者 (c) 作为一个真正的在单线程程序中减慢循环的 hacky 方法。在任何严肃的多线程软件中显式调用 Thread.sleep() 通常是一个糟糕的选择。

标签: java multithreading threadpool executorservice


【解决方案1】:

我不太确定语法,但您可以查看回调计时器。例如,您将 run() 方法分成两部分,preWork 和 postWork。完成 preWork 后,将对象添加到列表/地图/队列等,并带有“comeToLife”值。然后,您的线程将查看此队列,找到已达到“comeToLife”时间的其他对象,然后调用 postWork。

如果您需要线程在中断后立即运行,您应该使用 Lock 或其他机制,因为不会总是调用 InterruptException...

【讨论】:

    【解决方案2】:

    不,正在休眠的线程正在休眠。你不能让它做别的事情。

    您应该做的是添加一个计划任务,该任务会延迟您想要的时间。这将释放当前线程并允许它执行其他操作。

    ScheduledExecutorService ses = ...
    
    ses.submit(new Runnable() {
        @Override
        public void run() {
            //do preparation
            doPreWork();
    
            ses.schedule(new Runnable() {
                @Override
                public void run() {
                    //finish work
                    doAfterWork();
                }
            }, 40000);
        }                   
    }
    

    恕我直言,通过中断发送信号非常不可靠。不要编写依赖它的代码。

    【讨论】:

    • 好的,但是我该如何中断线程呢?例如,一个线程正在从流中读取用户命令并据此中断正在休眠的线程或使其再次休眠(在循环中)?
    • @Valera 读取线程是要中断线程还是触发要执行的任务?如果它想要执行任务,请将任务添加到 executorService。
    • @Valera 如果您中断一个线程,该线程现在可能正在做其他事情。例如另一个任务。如果您不在乎什么任务被打断或在什么时候被打断,那么这就是您想要的打断。 ;)
    • @Valera,中断的问题是,如果您的线程在调用库时被中断,您无法控制库认为中断应该意味着什么。一些库作者可能认为这意味着整个 JVM 将要关闭。他们可能会写完需要持久化到磁盘的任何内容,但您不能指望他们让库对象处于可以继续使用的状态。
    猜你喜欢
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 2019-08-12
    相关资源
    最近更新 更多