【问题标题】:Java, ThreadPoolExecutor, afterExecute, re-submit task?Java,ThreadPoolExecutor,afterExecute,重新提交任务?
【发布时间】:2012-06-23 13:59:57
【问题描述】:

我需要再次对队列执行正确完成的任务(某种循环)。是否可以重写 afterExecute 方法并调用 getQueue().offer(runnable); ?我担心线程同步,谢谢。

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    一个执行者可以运行不同的任务,而不仅仅是你想要重复的那个。因此,在覆盖的 afterExecute 方法中,您应该确定完成的任务是否是要重复的任务。结果,执行者知道特定的任务。这是一个糟糕的设计,INHO。

    考虑使用 ScheduledThreadPoolExecutor.scheduleWithFixedDelay()。但是,它要求延迟>0,但您可以将延迟设置为 1 纳秒。

    另一个选项(我更喜欢)是将您的任务包装在另一个 Runnable 中,如果嵌套任务正确完成,它将重新提交自身。

    【讨论】:

    • 有大量的小任务(对等服务器通信,未调度)。包装所有重复使用的任务——我试过了,但它不是昂贵的操作吗?
    • 如果您有大量的小任务,我建议您使用循环或集合将它们组合起来。每个 CPU 只需要一个任务来保持每个 CPU 忙碌。
    • 包装不会很昂贵,你不是在一个线程中启动一个线程,只是将一个对象包装在另一个对象中。但是,我认为这不是一个好方法,因为您将在重复执行时锁定线程,而不是在为其他操作提供服务后将其放回队列中以在下一个可用线程上执行
    • 我不喜欢 Runnable 重新提交自己的想法。这是因为这意味着 Runnable 必须有权访问正在调用它的执行程序。相反,我会做一个提交任务并在成功完成后由 Runnable 通知的管理器。经理将确定是否应重新提交 Runnable。这里有一点风险,Runnable 可能同时在多个线程中执行。但如果通知方法是最后一件事,就不会有风险。
    • @John B:我认为 Runnable 访问执行程序没有任何害处。想象一下,你实现了一个类似树的算法,比如快速排序——根任务为子数组生成子任务,等等。你认为外部经理适合这个吗?
    【解决方案2】:

    您的建议应该没有问题。但是,不要调用getQueue().offer(),而只需在执行程序服务上调用submit()。另外,由于afterExecute 是受保护的方法,我假设您已经创建了ThreadPoolExecutorService 的子类?请务必在您的 afterExecute 方法中调用 super.afterExecute()

    就个人而言,我喜欢提交者类的想法,该类负责将 Runnables 放在服务上。执行完成时使用回调通知提交者(可能使用Callable 而不是Runnable),提交者确定是否应重新提交任务。这可以很好地隔离潜在的关注点。

    最后,@Alexei 的建议可能是很好的建议,可以作为子类化ThreadPoolExecutorService 的更标准替代方案。

    【讨论】:

    • 是的,我有 TPE 子类,在覆盖的 afterExecute 方法中调用 super。正如您提到的,我想避免执行线程锁定的可能性。我想要类似的东西:获得完成的可运行检查状态,如果确定,则插入队列末尾以在将来执行(让线程处理另一个可运行)-类似于一些异步添加..
    • 您可以将Runnable 转换为允许检索状态并进行检查的其他类类型。这会起作用,但不是我认为的最佳解决方案。这是CallableFuture 的目的,但它们确实需要额外的线程来监控Futures
    猜你喜欢
    • 2016-05-23
    • 2013-02-08
    • 1970-01-01
    • 2016-06-01
    • 2016-02-18
    • 1970-01-01
    • 2014-08-23
    • 2017-09-17
    • 1970-01-01
    相关资源
    最近更新 更多