簡體   English   中英

如何在並行任務中運行並行任務

[英]How to run Parallel tasks inside parallel tasks

我們可以在執行程序服務中編寫Threadpool執行程序服務嗎? 誰能建議如何在並行任務中運行並行任務?

假設有10個任務需要並行運行,並且在每個任務中我必須運行100個並行任務。 有什么建議嗎

ExecutorService executor1 = Executors.newFixedThreadPool(8);
for (int i = 0; i < 8; i++) {
    ExecutorService executor2 = Executors.newFixedThreadPool(115);
    for (int j = 0; j < 115; j++) {
        Runnable worker = new UpdatecheckerTest(Region.getRegion(Regions.US_EAST_1),"");
        executor2.execute(worker);
      }
  }
executor1.shutdown();

這是正確的方法嗎?

這種方法會奏效,但是我認為正確的解決方案取決於您未提及的其他事項。

簡單案例

如果您要解決的問題非常簡單,簡短,則不是整個系統的很大部分,而性能或穩定性則不是問題。 我什至都不用使用線程池,而只使用並行流

您的代碼可能如下所示:

IntStream.range(0,8).().forEach(i -> {
    IntStream.range(0,115).parallel().forEach(j -> {
        new UpdatecheckerTest(Region.getRegion(Regions.US_EAST_1),"").run();
    });
});

整個系統的主要部分

如果您要解決的問題確實是系統的主要部分,那么當我查看您所描述的內容時,我實際上會看到一個大型任務,該任務代表着外循環(i循環)內部正在發生的事情以及一個小任務它表示內部循環(j循環)內部發生的情況。 如果這些任務在您的系統中起主要作用,則您可能希望將這些任務放在自己的類中,以使它們更具可讀性,可重用性,並且以后更易於更改。 您的代碼可能看起來像這樣:

SmallTask​​.java

import java.text.MessageFormat;

public class SmallTask implements Runnable {
    private String identifier;

    public SmallTask (String identifier) {
        this.identifier = identifier;
    }

    @Override
    public void run() {
        System.out.println(String.format(MessageFormat.format("Executing SmallTask with id: {0}", identifier)));
        // what ever happens in new UpdatecheckerTest(Region.getRegion(Regions.US_EAST_1),"").run()
    }
}

LargeTask.java

import java.text.MessageFormat;
import java.util.stream.IntStream;

public class LargeTask implements Runnable {
    private String identifier;

    public LargeTask (String identifier) {
        this.identifier = identifier;
    }

    @Override
    public void run() {
        System.out.println(String.format(MessageFormat.format("Executing LargeTask with id: {0}", identifier)));
        IntStream.range(0, 115).parallel().forEach(j -> {
            new SmallTask(identifier + "-" + String.valueOf(j)).run();
        });
    }
}

Main.java

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

public class Main {

    public static void main(String[] args) {
        IntStream.range(0,8).parallel().forEach(i -> {
            new LargeTask(String.valueOf(i)).run();
        });
    }
}

我什至更進一步地說,大型任務或啟動它的事件可能是事件驅動的體系結構中的事件,您可以將系統組織為具有各種事件,所有這些事件都可以異步執行。

性能和穩定性很重要

如果此代碼在您的系統中非常頻繁地運行,那么我將考慮使用線程輪詢,該線程輪詢可讓您控制正在使用的線程數,以及分配給運行LargeTask的線程是否與分配給運行SmallTask​​的線程相同。

那么您的代碼可能看起來像這樣:

SmallTask​​.java

import java.text.MessageFormat;

public class SmallTask implements Runnable {
    private String identifier;

    public SmallTask (String identifier) {
        this.identifier = identifier;
    }

    @Override
    public void run() {
        System.out.println(String.format(MessageFormat.format("Executing SmallTask with id: {0}", identifier)));
        // what ever happens in new UpdatecheckerTest(Region.getRegion(Regions.US_EAST_1),"").run()
    }
}

LargeTask.java

import java.text.MessageFormat;
import java.util.stream.IntStream;

public class LargeTask implements Runnable {
    private String identifier;

    public LargeTask (String identifier) {
        this.identifier = identifier;
    }

    @Override
    public void run() {
        System.out.println(String.format(MessageFormat.format("Executing LargeTask with id: {0}", identifier)));
        IntStream.range(0, 115).forEach(j -> {
            TasksExecutor.getSmallTaskExecutor().execute(new SmallTask(identifier + "-" + String.valueOf(j)));
        });
    }
}

TasksExecutor.java

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TasksExecutor {
    private static ExecutorService largeTasksExecutor = Executors.newFixedThreadPool(8);
    private static ExecutorService smallTaskExecutor = Executors.newFixedThreadPool(115);

    public static ExecutorService getLargeTaskExecutor () {
        return largeTasksExecutor;
    }

    public static ExecutorService getSmallTaskExecutor () {
        return smallTaskExecutor;
    }
}

Main.java

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

public class Main {

    public static void main(String[] args) {
        IntStream.range(0,8).forEach(i -> {
            TasksExecutor.getLargeTaskExecutor().execute(new LargeTask(String.valueOf(i)));
        });
    }
}

如果需要,不要忘記添加功能來關閉線程池。 也許在每個任務和您要管理它的特定線程池之間添加某種依賴注入 ,這將在以后為您提供更好的靈活性

如果您想更進一步,則可以使用Messaging Framework,在其中可以使用不同的隊列來管理所有需要執行的任務。 ZeroMQKafka

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM