使用 ExecutorService 将任务确定性分配给线程

2024-01-18

给定 Executor 服务具有固定的线程池,是否可以保证任务到线程的确定性分配?更准确地说,假设只有两个线程,即 pool-thread-0 和 pool-thread-1,并且有 2 个要执行的任务的集合。我希望实现的是前一个线程始终执行第一个线程,而后者处理剩余的线程。

这是一个例子:

public static void main(String[] args) throws InterruptedException, ExecutionException {
    ExecutorService executorService = newFixedThreadPool(2,
            new ThreadFactoryBuilder().setNameFormat("pool-thread-%d").build());

    for (int i = 0; i < 5; i++) {
        List<Callable<Integer>> callables = ImmutableList.of(createCallable(1), createCallable(2));
        executorService.invokeAll(callables);

    }
}

public static Callable<Integer> createCallable(final int task) {
    return new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            currentThread().sleep(1000);
            System.out.println(Thread.currentThread().getName() + " executes task num: " + task);
            return task;
        }
    };
}

我的机器的示例输出:

pool-thread-0 executes task num: 1
pool-thread-1 executes task num: 2

pool-thread-0 executes task num: 2
pool-thread-1 executes task num: 1

pool-thread-0 executes task num: 2
pool-thread-1 executes task num: 1

pool-thread-0 executes task num: 2
pool-thread-1 executes task num: 1

pool-thread-0 executes task num: 1
pool-thread-1 executes task num: 2

简而言之,我希望确保 pool-thread-0 始终执行第一个任务。任何帮助将不胜感激!


ExecutorService 并非旨在为其 Callable/Runnable 提供“线程亲和力”。有人可能会说“这就是重点”,API 的作用是让程序员处理工作描述(Callable),而不是线程处理。

您的设计,“有一个与每个线程关联的随机数据生成器”不适合 ExecutorService,我认为有以下三个原因:

  1. 您无法控制将创建(或销毁!)以及何时创建(或销毁!)哪些线程(如果一个线程崩溃了怎么办?池将重新创建它,但它将获得什么随机生成器?)。因此,我们无法推断出一种可靠的方式来表示“这个线程”有“这个生成器”,更不用说“第二个”线程有“这个生成器”了,因为甚至可能没有第二个线程(如果每个任务都如此之快怎么办?他们的治疗速度比你派遣他们的速度还要快?)。

  2. 您无法控制何时执行哪些任务。好吧...使用 Executors.newFixedThreadPool,您可以按照提交顺序分派它们,但据您所知,操作系统调度程序可能会将所有优先级赋予线程 1,最终将完成所有工作,并且线程 2 将不执行任何操作(可以是两者之间的任意比例)。

  3. 将“数据生成器”传递给线程的唯一方法是重写执行程序服务的 ThreadFactory。否则,您无法访问线程实例(除了运行时可调用本身之外)。因此,要将特定的生成器关联到特定的线程,您必须知道当前正在创建哪个线程号,如果您正在计算线程数,这很容易,但如果您想知道这是什么 Callable,则很困难线程的目的是(参见第 2 点)。

因此,我强烈建议您定义一些其他方式将工作单元与数据生成器关联起来,因为“线程实例”通常不可靠 - 至少通过执行器服务不可靠。 例如。当你说

我需要保证它们处理的线程和数据的组合是可重复的。

据我所知,您将始终分派一定数量的 Callable,并且您需要每个 Callable 来处理由特定生成器发出的特定数据集。假设我们有给定数量的任务和 3 个生成器,task(N) 将使用生成器N%3.

为了使结果可重复,您还需要使用同一生成器的任务不要同时执行(您希望通过线程亲和力实现什么?)。

有一定数量的模式可以实现这一点。

1 是:重构为生产者/消费者(反之亦然)

在你的执行器服务中创建 3 个任务,每个任务都监听一个BlockingQueue(其私人等候名单)并拥有自己的私人发电机。这些是消费者。
让你的主线程成为生产者:当它创建工作单元(曾经是一个Callable在你原来的设计中)编号为N,将其调度到编号为N%3的等待队列。就是这样:每个消费者将按照您希望的顺序按顺序接收自己的数据以进行计算。你们已经达到了“缘分”。

2是:让任务自己派发任务。 (用 hacky 的方式来做)

首先,重构您的可调用对象以链接到它们需要使用的生成器。 然后,在主线程上,构建要为每个生成器运行的任务列表。
从主线程为每个生成器分派第一个任务。
在每个可调用对象的末尾,使可调用对象从其列表中调度下一个工作单元。
不过,请注意不要“将您锁定”,如果您从可调用对象分派可调用对象,请不要等待结果,因为这将阻止可调用对象完成,进而阻止新分派的执行。这是一个僵局。

3是:与2相同,效率较低,但风险较小

不要从可调用对象内部分派可调用对象,而是通过等待 future 来仅从主线程分派。

使用这两种方式中的任何一种,都不能保证哪些任务将首先完成或最后完成,但可以保证您分派的工作单元可预测地与您控制的数据生成器相关联,并且它们将按照您分派的顺序执行他们。希望这已经足够了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ExecutorService 将任务确定性分配给线程 的相关文章

  • 返回一个dispatch_async获取的变量[重复]

    这个问题在这里已经有答案了 基本上 一个方法需要返回一个在dispatch async中获取的NSDictionary 这是我尝试过的 NSDictionary fetchNSDictionary dispatch queue t Queu
  • Python 中 time.sleep 和多线程的问题

    我对 python 中的 time sleep 函数有疑问 我正在运行一个脚本 需要等待另一个程序生成 txt 文件 虽然 这是一台非常旧的机器 所以当我休眠 python 脚本时 我遇到了其他程序不生成文件的问题 除了使用 time sl
  • 未装饰窗户的 Windows Snap 功能?

    有谁知道如何允许未装饰的窗户使用此功能 唯一的选择就是重新实施它 有任何想法吗 谢谢 可停靠可能是唯一的JToolBar http docs oracle com javase tutorial uiswing components too
  • JOOQ 忽略具有默认值的数据库列

    看来JOOQ完全忽略了数据库列的默认值 既不会更新 ActiveRecord 对象 也不会在 INSERT 时跳过此列 相反 它尝试将其设置为 NULL 这在 NOT NULL 列上失败 Example CREATE TABLE bug f
  • 单线程程序中可以有竞争条件吗?

    您可以在here https en wikipedia org wiki Race condition Software关于什么是竞争条件的一个很好的解释 我最近看到很多人对竞争条件和线程做出了令人困惑的陈述 我了解到竞争条件只能发生在线程
  • 将类转换为 JSONObject

    我有好几堂这样的课 我想将类转换为 JSONObject 格式 import java io Serializable import com google gson annotations SerializedName public cla
  • JAXB - 忽略元素

    有什么方法可以忽略 Jaxb 解析中的元素吗 我有一个很大的 XML 文件 如果我可以忽略其中一个大而复杂的元素 那么它的解析速度可能会快很多 如果它根本无法验证元素内容并解析文档的其余部分 即使该元素不正确 那就更好了 例如 这应该只生成
  • 如何更改 Swagger-ui URL 前缀?

    我正在使用 Springfox Swagger2 和 Spring boot 1 5 9 我可以通过此链接访问 swagger UI http localhost 8090 swagger ui html http localhost 80
  • 使用 JDBC 连接到 PostgreSql 的本地实例

    我在 Linux 机器上有一个正在运行的 PostgreSql 本地实例 当我使用psql来自 shell 的命令我成功登录 没有任何问题 我需要通过 JDBC 连接到 PostgreSql 但我不知道我到底应该传递什么url参数为Driv
  • 为什么解析这个 JSON 会抛出错误?

    我正在尝试解析这个 JSONObject query yahoo count 1 results rate Name USD INR id USDINR Time 12 19pm Date 10 31 2015 Bid 65 405 Ask
  • 类更改(例如字段添加或删除)是否保持 Serialized 的向后兼容性?

    我有一个关于 Java 序列化的问题 在这种情况下 您可能需要修改可序列化类并保持向后兼容性 我有丰富的 C 经验 所以请允许我将 Java 与 NET 进行比较 在我的Java场景中 我需要使用Java的运行时序列化机制序列化一个对象 并
  • Android - 存储对ApplicationContext的引用

    我有一个静态 Preferences 类 其中包含一些应用程序首选项和类似的内容 可以在那里存储对 ApplicationContext 的引用吗 我需要该引用 以便我可以在不继承 Activity 的类中获取缓存文件夹和类似内容 你使用的
  • 如何使用 Jersey 将嵌套列表封送为 JSON?我得到一个空数组或一个包含数组的单元素字典数组

    我正在开发一个使用 Jersey 将对象转换为 JSON 的项目 我希望能够写出嵌套列表 如下所示 data one two three a b c 我想要转换的对象首先将数据表示为 gt gt 我认为 Jersey 会做正确的事情 以上输
  • Azure Java SDK:ServiceException:ForbiddenError:

    尝试了基本位置检索器代码 如下所示 String uri https management core windows net String subscriptionId XXXXXXXX 5fad XXXXXX 9dfa XXXXXX St
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • 在 Java 中通过 D-Bus MPRIS 访问 Clementine 实例

    我使用 Clementine 作为音乐播放器 它可以通过 D Bus 命令进行控制 在命令行上 使用 qdbus 我可以 Start Stop 暂停播放器 强制它跳过播放列表中的歌曲 检查播放列表的长度 检查播放列表中当前播放的曲目及其元数
  • 带 getClassLoader 和不带 getClassLoader 的 getResourceAsStream 有什么区别?

    我想知道以下两者之间的区别 MyClass class getClassLoader getResourceAsStream path to my properties and MyClass class getResourceAsStre
  • 什么是 Java2D 处理程序线程?

    我创建了一个使用 Hibernate 的示例 java 应用程序 当我进行线程转储时 我观察到一个名为 Java2D Disposer 的奇怪线程 有人能告诉我该线程的功能吗 AWT 系统中的某些实体需要最终确定以释放资源 最突出的例子是j
  • Java 的“&&”与“&”运算符

    我使用的示例来自 Java Herbert Schildt 的完整参考文献 第 12 版 Java 是 14 他给出了以下 2 个示例 如果阻止 第一个是好的 第二个是错误的 因此发表评论 public class PatternMatch
  • Spring 作为 JNDI 提供者?

    我想使用 Spring 作为 JNDI 提供程序 这意味着我想在 Spring 上下文中配置一个 bean 可以通过 JNDI 访问该 bean 这看起来像这样

随机推荐

  • Vista/Win2008 上的关键部分泄漏内存?

    看来在 Vista Windows Server 2008 中大量使用关键部分会导致操作系统无法完全重新获得内存 我们在 Delphi 应用程序中发现了这个问题 这显然是因为使用了 CS API 看这个所以问题 https stackove
  • 将 swf 转换为 mp4

    这个答案没有帮助 将压缩的 swf 转换为 mp4 https stackoverflow com q 20194270 630169 尝试转换 swf 文件 ffmpeg 输出 ffmpeg i GTDS demo new swf GTD
  • 如何使 spring @retryable 可配置?

    我有这段代码 Retryable maxAttempts 3 stateful true include ServiceUnavailableException class exclude URISyntaxException class
  • jquery读取嵌套的json

    我有以下 json 如下所示 我正在尝试读取值 TOP1 TOP2 我有点不确定该怎么做 我正在使用以下内容 但这只会给我一个包含 TOP1 和 TOP2 嵌套对象的对象 如何获取 TOP1 和 TOP2 值 getJSON http lo
  • 将 TArray 类型转换为 X 数组是否安全?

    今天我发现了一个编译器错误 QC 108577 http qc embarcadero com wc qcmain aspx d 108577 以下程序无法编译 program Project1 APPTYPE CONSOLE proced
  • 系统找不到JavaApplicationLauncher

    我正在运行 Mac OS X 版本 12 0 1 也称为 Monterey 我已经安装了 MultiWii 程序来控制我正在构建的无人机 本教程逐步介绍下载 解压 甚至适用于 MacOS 的特殊 chmod 指令 然而 当我尝试运行 Mul
  • 读取、读取部分读取

    我似乎无法在文档中找到有关此内容的信息 The read系统调用文档说它读取的数据可能少于指定的数据 做read尝试阅读几次 我知道fread是一个包装器read 当我调用fread 它是否有可能多次从流中读取 直到它变为 0 或读取指定的
  • 如何围绕轮廓绘制矩形?

    我刚刚开始使用 opencv 我正在尝试制作一个程序 在沙子上的岩石图片周围放置方块 该函数的文档here http docs opencv org modules imgproc doc structural analysis and s
  • 如何将 Vec> 移动到 Vec>>

    我有一个Vec
  • Python 中使用回溯记录异常

    如何记录 Python 异常 try do something except How can I log my exception here complete with its traceback Use logging exception
  • 弹性容器中的等高行

    如您所见 list items在第一个row有相同的height 但第二个项目row有不同的heights 我希望所有物品都有统一的height 有什么方法可以在不付出的情况下实现这一目标固定高度并且只使用flexbox 这是我的code
  • 向上滚动时折叠工具栏图像消失

    我正在尝试实现一个带有大标题图像的折叠工具栏 我希望图像开始时非常大 并且它有效 并且不完全崩溃 这也有效 问题是 当工具栏达到最小可折叠高度时 图像会消失 并褪色为应用程序的主要颜色 我希望图像即使在折叠时也保持可见 另外 后退按钮与图片
  • 可观察集合替换项目

    我有一个ObservableCollection 我可以从集合中添加和删除项目 但我无法替换集合中的现有项目 有一种方法可以替换项目并将其反映在我的绑定组件上 System Collections Specialized NotifyCol
  • TPL 数据流:为什么 EnsureOrdered = false 会破坏此 TransformManyBlock 的并行性?

    我正在研究 TPL 数据流管道 并注意到与排序 并行性相关的一些奇怪行为TransformManyBlocks 也可能适用于其他块 这是我要重现的代码 NET 4 7 2 TPL Dataflow 4 9 0 class Program s
  • 如何删除单元格中第一个空格之后的所有字符?

    我有一个城市名称列表 后跟它们所在的州 所有这些都在 Excel 的一列中 如何删除第一个空格之后的所有内容 以便城市名称成为单元格中唯一保留的内容 示例 A1 约翰逊德克萨斯州 应该只是 A1 约翰逊 我假设你想要一个 VBA 解决方案
  • 使用 vscode 扩展 API 更改文件 EOL

    我可以在 VSCode 中默默地更改行尾顺序吗 像这样的事情 vscode commands executeCommand workbench action editor changeEOL LF 您可以将此行添加到您的用户首选项设置中 C
  • 应用按键后捕获 HTML 文本输入按键?

    完全是新手问题 所以请耐心等待 当 HTML 文本输入控件中发生按键时 有两个事件似乎对管理按键很有用 onKeyPress 和 onChanged onKeyPress 在按下按键后 但在将操作应用于控件的文本之前触发 仅当焦点从控件中移
  • 使用 webdriver 查找元素的最佳且最快的方法是什么? By.XPath 或 By.ID 还是其他?为什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 使用 webdriver 查找元素的最佳且最快的方法是什么 By XPath 或 By ID 还是其他 为什么 我在很多地方都读到 XPath
  • 替换字符串中的字符,而不使用字符串replace()方法[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有一个字符串 String originalString This car is my car 我想用 自行车 替换 汽车 而不使用字符
  • 使用 ExecutorService 将任务确定性分配给线程

    给定 Executor 服务具有固定的线程池 是否可以保证任务到线程的确定性分配 更准确地说 假设只有两个线程 即 pool thread 0 和 pool thread 1 并且有 2 个要执行的任务的集合 我希望实现的是前一个线程始终执