java - 线程提交给ExecutorService后运行(执行)的顺序是什么?

标签 java multithreading synchronization thread-safety filewriter

是否有比同步方法或文件写入器更好的方法来使写入文件线程安全(对于文件在每个线程中可能不完全相同的情况)?我读了一些与此主题类似的帖子,但它们似乎专注于一个文件而不是多个文件。

例如。有 20 个线程向文件写入(这意味着它使用一种方法创建文件写入器,然后使用 try-catch 等写入文件);其中 10 个线程写入 fileA,5 个线程写入 fileB,4 个线程写入 fileC,1 个线程写入 fileD。

同步该方法效率不高,因为想要写入不同文件的线程必须等待前一个线程完成才能继续。我认为同步文件编写器的作用几乎相同,还是我错了?

如果我有一个单独的线程(来自主应用程序)写入文件,它们会按照用 1 个线程提交给 ExecutorService 的顺序执行(运行)吗?

在主应用程序中,我将向 ExecutorService 提交新线程(使用 1 个线程)。线程将写入文件(使用从 Logger 类同步 FileWriter 的写入方法)。线程会一个接一个地写入文件,因为 FileWriter 是同步的,而 ExecutorService 只有 1 个线程,这将防止同时多次写入同一个文件。问题是线程是否会按照提交给 ExecutorService 的顺序写入文件?我知道它们按照提交的顺序开始,但我不太确定执行顺序。

最佳答案

您混淆了一些东西,从而造成了困惑:首先,ExecutorService 是一个接口(interface),它不强制规定提交任务(不是线程)的特定方式被执行。因此,询问 ExecutorService 如何执行特定的操作是没有意义的,因为它没有被指定。它甚至可能会删除所有任务而不执行任何操作。

其次,如上所述,您向 ExecutorService 提交任务,而不是线程,而任务可能实现 Runnable可调用

不幸的是,Java 中存在一个设计缺陷,Thread 实现了 Runnable,因此您实际上可以将 Thread 实例传递给 submit() 你永远不应该这样做,因为它会造成很多困惑而没有任何好处。当您这样做时,常见的 ExecutorService 实现会将其视为普通的 Runnable 调用其 run() 方法,完全忽略它是一个 Thread 实例。与该 Thread 实例关联的线程资源与实际执行 run() 方法的线程没有任何关系(如果实现曾经调用run())。

因此,如果您将作为 RunnableCallable 实现的任务提交给 ExecutorService,您必须研究特定实现的文档以了解他们将如何被执行。

例如如果您使用Executors.newSingleThreadExecutor()要获得实现,其文档显示:

Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.

(我强调)

这样就可以完全回答你的问题了。请注意,在这种情况下,您甚至不需要在任务实现中进行同步,因为此 ExecutorService 已经提供了任务所需的互斥保证。

关于java - 线程提交给ExecutorService后运行(执行)的顺序是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24976977/

相关文章:

java - 即使我们有多个核心来服务请求,单例对象也会导致性能下降吗?

java - 该行有多个标记

ios - 数组回调

java - 同步可以作为AOP中的一个方面吗

不同 Azure 帐户中托管的数据库之间的 Azure DB 同步或镜像

C# 同步对象 - 具有写入访问器的重复代码

java - 使用 Guava MapMaker/CacheBuilder 处理空值

Java jsoup - 清除除链接以外的所有标签

Java:强制停止 ExecutorService 线程

java - Java NetBeans 上的批量读取错误(列车调度)