我想安排Runnables并从同一个线程一个接一个地执行它们,但是在指定的超时后不是更早。有没有一种标准的方法呢?
这是我的代码:
public class DelayedExecutor {
private final long _timeout;
private final List<Runnable> _tasks = new LinkedList<>();
private final ThreadFactory _factory;
private final Thread _supervisor;
public DelayedExecutor(long timeout, ThreadFactory factory) {
_timeout = timeout;
_factory = factory;
_supervisor = new Thread(new Runnable() {
@Override
public void run() {
while (_supervisor.isInterrupted()) {
try {
Thread.sleep(_timeout);
}
catch (InterruptedException e) {
if (_supervisor.isInterrupted())
break;
}
synchronized (_tasks) {
ArrayList<Runnable> prepared = new ArrayList<>(_tasks);
Collections.reverse(prepared);
execute(prepared);
_tasks.clear();
}
}
}
});
_supervisor.setDaemon(true);
_supervisor.start();
}
public void schedule(Runnable runnable) {
synchronized (_tasks) {
_tasks.add(runnable);
}
}
private void execute(final List<Runnable> tasks) {
_factory.newThread(new Runnable() {
@Override
public void run() {
for (Runnable runnable : tasks)
runnable.run();
}
});
}
}
答案 0 :(得分:2)
经过一些刺耳的评论之后,我想我已经开始明白你在做什么,看起来像Producer
/ Consumer
模式有一个小修改。根据我们的聊天,我现在明白你想以固定费率运营消费者!这应该给你一个想法(但在你的实现中使用并发集合):
public FixedRateConsumer implements Runnable
{
private final object _lock = new object();
// *** use a concurrent collection here ***
private Queue<Runnable> _workQueue;
public FixedRateConsumer()
{
_workQueue = new Queue<Runnable>();
}
public scheduleTask(Runnable task)
{
synchronized(_lock)
{
_workQueue.put(task);
}
}
public void run()
{
synchronized(_lock)
{
while(_workQueue.poll()!=null)
{
_workQueue.take().run();
}
}
}
}
现在你只需安排消费者按固定费率运行:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
FixedRateConsumer consumer = new FixedRateConsumer();
scheduler.scheduleAtFixedRate(consumer, /*specify initial delay*/, /*specify rate*/, /*specify TimeUnit*/);
您的制作人可以安排这样的任务:
// Then you just schedule your tasks like this
consumer.scheduleTask(new Runnable());
答案 1 :(得分:1)
最好的办法是使用ScheduledThreadExecutor。您可以使用一个线程池创建它:
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
然后查看schedule
和scheduleAtFixedRate
方法。
答案 2 :(得分:0)
一种方法是创建一个ExecutorService
,并将线程池大小设置为1并在run()
方法结束时等待,或者将另一个Runnable
放入其中run()
{{1}} 1}}进入你已经拥有的Runnables之间的队列。
Link虽然提出了一个很好的问题,但实际上你将按顺序运行这些任务。
答案 3 :(得分:0)
如果您希望一次性运行它们而不是按顺序运行它们,那么CountDownLatch
可以提供帮助。
int threads = 10;
final CountDownLatch ready = new CountDownLatch(threads);
final CountDownLatch start = new CountDownLatch(1);
ExecutorService executorService = Executors.newFixedThreadPool(threads);
for(int i=1; i<=threads; i++) {
executorService.execute(new Runnable() {
public void run() {
ready.countDown(); //Signal that this runnable is ready
try {
start.await(); //Wait for the signal
} catch(InterupptedException e) {}
Target target = new Target();
target.doSomeStuff();
}
});
}
try {
ready.await(); //Wait till all are ready
} catch (InterruptedException e) {
e.printStackTrace();
}
start.countDown(); //And off they go