2012-02-23 68 views
2

从标题的想法演示一个代码示例:在java并发包中有没有任何执行器可以确保所有任务都按照提交顺序完成?

executor.submit(runnable1); 
executor.submit(runnable2); 

我需要确保runnable1将完成前runnable2开始,我还没有找到执行人文档中这样的行为的任何证据。

关于我正在解决的问题: 我需要将大量日志写入文件。每个日志需要很多预计算(格式化和其他一些东西)。所以,我想把每个日志记录任务放到一个队列中,并在一个单独的线程中处理这些任务。当然,保持日志排序非常重要。

回答

4

单线程执行程序将按提交的顺序执行所有任务。如果您想要同时执行任务,则只能使用具有多个线程的线程池。

将任务添加到队列本身可能很昂贵。您可以使用队列或创建对象使用一个交换这样

http://vanillajava.blogspot.com/2011/09/exchange-and-gc-less-java.html?z#!/2011/09/exchange-and-gc-less-java.html

该避免的。

速度更快的替代方法是使用不需要后台线程的内存映射文件(实际上操作系统在后台工作),这又快得多了。它支持每秒几微秒的延迟和数百万条消息。

https://github.com/peter-lawrey/Java-Chronicle

0

您可以创建一个简单的包装像下面这样使你的所有的Runnable都在同一个线程(即顺序)执行,并提交包装执行人来代替。这并没有解决日志记录问题。

class MyRunnable implements Runnable { 

    private List<Runnable> runnables = new ArrayList<>(); 

    public void add(Runnable r) { 
     runnables.add(r); 
    } 
    @Override 
    public void run() { 
     for (Runnable r : runnables) { 
      r.run(); 
     } 
    } 

} 

//...... 
MyRunnable r = new MyRunnable(); 
r.add(runnable1); 
r.add(runnable2); 
executor.submit(r);  
0

假设你正在做一些日志文件的后分析?你有没有考虑过他们写的订单,以后再离线重新订购。您可以在提交时使用时间戳或AtomicLong分配唯一的ID吗?

代码草图(未经测试)是这样的:

import java.util.concurrent.atomic.AtomicLong; 

class MyProcessor { 

    public void work() 
     for (Object data: allData) { 
      executor.submit(new MySequencedRunnable(data); 
     } 
    } 

} 

class MySequencedRunnable implements Runnable { 
    private static final AtomicLong LOG_SEQUENCE_ID = new AtomicLong(0); 

    private final Object data; 

    MySequencedRunnable(Object data) { 
     this.data = data; 

    } 

    public void run() { 
     LOGGER.log(LOG_SEQUENCE_ID.incrementAndGet(), data); 
    } 

}

也可以考虑,如果你正在使用类似的log4j,使用NDCMDC,以协助重新排序。

相关问题