有没有比同步方法或文件编写器更好的方法来编写文件线程安全(对于文件在每个线程中可能不完全相同的情况)?我读了一些类似于这个主题的线程,但它们似乎只关注一个文件而不是多个文件。
实施例。有20个线程写入(意味着它使用一种方法,为文件创建文件写入器,然后使用try-catch等写入它)到文件; 10个线程写入fileA,5个线程写入fileB,4个线程写入fileC,1个线程写入fileD。
同步该方法效率不高,因为想要写入不同文件的线程必须等待前一个线程完成才能继续。我认为同步文件编写器几乎一样,或者我错了?
如果我有一个单独的线程(来自主应用程序)写入文件,它们是否会按照用1个线程提交给ExecutorService的顺序执行(运行)?
在主应用程序中,我将向ExecutorService提交新线程(使用1个线程)。线程将写入文件(使用具有从Logger类同步的FileWriter的write方法)。线程将逐个写入文件,因为FileWriter是同步的,并且ExecutorService只有一个线程,这将阻止同时对同一文件进行多次写入。问题是线程会按照提交给ExecutorService的顺序写入文件吗?我知道他们按照提交的顺序开始,但我对执行顺序不太确定。
答案 0 :(得分:3)
你正在混淆一些会引起混淆的事情:首先,ExecutorService
是一个接口,它不会强制执行提交任务(不是线程)的特定方式。因此,询问ExecutorService
如何处理某个特定事物是没有意义的,因为它没有指定。它甚至可以在不执行任何操作的情况下丢弃所有任务。
其次,如上所述,您正在向ExecutorService
提交任务而非线程,而任务可能会实现Runnable
或Callable
。< / p>
不幸的是,Thread
实现Runnable
的Java存在设计缺陷,因此您实际上可以将Thread
实例传递给submit()
,这样您就不应该这样做了,因为它创建了很多混淆无益。执行此操作时,常见的ExecutorService
实现会将其视为普通Runnable
调用其run()
方法,完全忽略它是Thread
实例的事实。与该Thread
实例关联的线程资源与实际执行run()
方法的线程没有任何关系(如果实现曾调用run()
)。
因此,如果您将Runnable
或Callable
实施的任务提交给ExecutorService
,则必须学习特定实施的文档,以了解它们将如何执行。
E.g。如果你使用Executors.newSingleThreadExecutor()
来获得实现,它的文档说:
创建一个Executor,它使用一个在无界队列中运行的工作线程。 (但请注意,如果此单个线程由于在关闭之前执行期间的故障而终止,则在执行后续任务时需要新的一个线程。)保证任务按顺序执行,并且不超过一个任务将在任何给定时间激活。与其他等效的
newFixedThreadPool(1)
不同,保证返回的执行程序不可重新配置以使用其他线程。
(我强调)
这样可以完全回答你的问题。请注意,在这种情况下,您在任务的实施中甚至不需要synchronized
,因为此ExecutorService
已经提供了您的任务所需的互斥保证。
答案 1 :(得分:2)
考虑使用专用文件编写器线程的替代方法,该线程是写入文件的唯一线程。其他线程可以安全地将消息添加到java.util.concurrent.BlockingQueue
。一旦线程在队列上放置了一条消息,它就可以恢复工作。