※ 引述《lin1987www (林奕忠)》之铭言:
: 以下挑战白话文解说
: 我固定请了5个员工,然后分配5个员工去从生产,而工厂的生产前,
: 必须有人去打开电源,才能使机械运作,才能开始生产。
: 若有1个员工要从事生产时,若发现电源没开的话,
: 就会请下一个员工,也就是第2名员工,去打开电源开关。
: 当我工厂要一口气生产4个产品的时候,就会一口气有4个人冲向机台,
: 等待开工,这时第5个人就会去打开电源开关。
: 很不幸的事,我一口气要生产5个产品的时候,就有5个人冲向机台,
: 但是没有人去打开电源,因为我一开始就说了,我只请5个员工 Orz
: 然后整个工厂就停工了 ...
: ◢▆▅▄▃崩╰(〒皿〒)╯溃▃▄▅▇◣
: Thread 有办法限制说不会进行 wait吗?
: 或者变成 non-blocking 的形式有可能吗?
: 或者该怎么避免此问题的发生呢?
: 从描述可以看的出来勤俭持家的我是用
: Executors.newFixedThreadPool
: 而不是用有钱人专用的 ( 大误 )
: Executors.newCachedThreadPool
: 小弟我想请教 大大们都怎样解决这问题? Q"Q
当你使用Executor (或说Thread Pool)
你的每个Task本质上就不应该这样设计
不应该会有任何动作是会Block太久
甚至最好都是non-blocking的方法,
但是我没有那么极端,
只要不要是呼叫wait或是sleep这种就好
可以接受预期时间会回来的IO或是synchronized block或method
以你的case
我假设你的程式大概长这样
public class WorkingTask extends xxTask {
public void run() {
if(!isEngineStarted()) {
executors.execute(new StartEngineTask());
waitForEngineStart();
}
startWorking();
}
}
但这种会等,而且不会有预期开始的动作,
在Task里面就是一种类似"占著茅坑不拉屎"的感觉
比较简单的改法应该是这样
public class WorkingTask extends xxTask {
public void run() {
if(!isEngineStarted()) {
if(!isEngineStarting()) {
scheduledExecutors.execute(new StartEngineTask());
}
scheduledExecutors.schedule(new WorkingTask(),
1, TimeUnit.SECONDS); // postpone current task 1 second
return;
}
startWorking();
}
}
这种做法就是你的task永远都不会占住
而发现没开的话,就async打开
并且每一秒钟去看一下是否engine打开并且往下做..
还有不知道你的这些"员工"数量会很多吗?
如果真的没有很多的话,
而且每个Task会要跑很久的话
甚至是要跑道某个人叫停才会停的task的话
ThreadPool这种方法不太适合你..
就每个task开一个thread比较适合