带多线程的计划多任务处理,没有线程重叠
Scheduled MultiTasking With MultiThreading without overlapping of threads
我有 5 个参数化线程指向 5 个文件夹,其中参数是文件夹的名称。假设 FolderNames 是 A、B、C、D 和 E。
每个文件夹都会有多个文件,需要对其进行一定的操作
对每个文件夹下的所有文件执行的操作将是相同的,即任务将是相同的。整个事情需要不断 运行 即它必须在一个时间表中。
我尝试过的事情:
使用多线程调度(即 5 个参数化线程在同一个任务上工作)-> 但这会导致线程重叠,因为任务是常见的并且不会生成所需的输出。
使用多任务安排,即为每个实现 Runnable 的文件夹创建一个单独的 class,并为每个 class 使用 executor.scheduleAtFixedRate。这将导致同步操作,这意味着在对第一个文件夹的操作未结束之前,不会开始处理其他 4 个文件夹。我们不能增加 newScheduledThreadPool 中的 corePoolSize,因为它会产生与第 1 点相同的重叠问题。
所以我正在寻求帮助来解决我的线程与基础任务不重叠的问题。
Summary of above problem in Pictorial Form
场景 2 的虚拟代码:
class FolderA implements Runnable{
private final String fileName;
FolderA(String fileName){
this.fileName=fileName;
}
@Override
public void run() {
ScheduleJob.insideRun(fileName);
}
}
class FolderB implements Runnable{...}
class FolderC implements Runnable{...}
class FolderD implements Runnable{...}
class FolderE implements Runnable{...}
public class ScheduleJob{
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
FolderA folderA = new FolderA("folderA");
executor.scheduleAtFixedRate(folderA, 60,60, TimeUnit.SECONDS);
FolderB folderB = new FolderB("folderB");
executor.scheduleAtFixedRate(folderB, 60,60, TimeUnit.SECONDS);
--and same for Folder C D and E
public static void insideRun(String folderName){
//Contains call to various operations that need to
be perfomed on each file present in Folder A B C D and E
Operation order : Read, Process, Write for each file
}
}
您的问题不清楚,但我猜您希望处理一个文件夹中的文件时不会阻碍或阻止处理其他文件夹中的文件。
多个 ExecutorService
个对象
创建多个 ExecutorService
对象。每个执行程序服务都专注于一个文件夹。如果你有五个文件夹,有五个执行器服务,每个文件夹一个执行器服务。
如果您希望每个文件夹一次只处理一个文件,请将每个执行程序服务设置为单线程。
将您的任务(您的 Runnable
或 Callable
)定义为采用指示要处理哪个文件夹的参数。
public void FileProcessor implements Runnable
{
// Constructor
public FileProcessor( Path path ) { … }
// Implement `Runnable`
@Override
public void run() { … }
}
定义您的文件夹。
List< Path > folders = List.of( pathToA, pathToB, … ) ;
将它们提供给执行程序服务的构造函数。
List< ExecutorService > executorServices = new ArrayList<>() ;
for( Path folder : folders )
{
ExecutorService es = Executors. newSingleThreadExecutor() ;
executorServices.add( es ) ;
es.submit( new FileProcessor( folder ) ) ;
}
然后使用该集合 executorServices
正常关闭所有执行程序服务。
对于预定的执行程序服务,同样的想法。将类型从 ExecutorService
更改为 ScheduledExecutorService
。呼叫Executors.newSingleThreadScheduledExecutor
。将 submit
方法更改为其中一种计划方法。
请注意,即使本答案中提供的解决方案也不能保证所有文件夹都将得到同等的处理。每个执行程序服务将由其自己的线程支持。何时安排线程在 CPU 内核上执行以及执行多长时间取决于主机 OS 和 JVM。
作为 Java 程序员,我们无法直接控制每个线程执行多少工作或执行何种顺序。在运行时,完全有可能文件夹 B 可能处理十几个文件,而文件夹 A 只完成三个文件,而文件夹 C 完成 none。一般来说,您会看到随着时间的推移平均工作量,但短期内可能会有所不同。
我有 5 个参数化线程指向 5 个文件夹,其中参数是文件夹的名称。假设 FolderNames 是 A、B、C、D 和 E。
每个文件夹都会有多个文件,需要对其进行一定的操作
对每个文件夹下的所有文件执行的操作将是相同的,即任务将是相同的。整个事情需要不断 运行 即它必须在一个时间表中。
我尝试过的事情:
使用多线程调度(即 5 个参数化线程在同一个任务上工作)-> 但这会导致线程重叠,因为任务是常见的并且不会生成所需的输出。
使用多任务安排,即为每个实现 Runnable 的文件夹创建一个单独的 class,并为每个 class 使用 executor.scheduleAtFixedRate。这将导致同步操作,这意味着在对第一个文件夹的操作未结束之前,不会开始处理其他 4 个文件夹。我们不能增加 newScheduledThreadPool 中的 corePoolSize,因为它会产生与第 1 点相同的重叠问题。
所以我正在寻求帮助来解决我的线程与基础任务不重叠的问题。
Summary of above problem in Pictorial Form
场景 2 的虚拟代码:
class FolderA implements Runnable{
private final String fileName;
FolderA(String fileName){
this.fileName=fileName;
}
@Override
public void run() {
ScheduleJob.insideRun(fileName);
}
}
class FolderB implements Runnable{...}
class FolderC implements Runnable{...}
class FolderD implements Runnable{...}
class FolderE implements Runnable{...}
public class ScheduleJob{
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
FolderA folderA = new FolderA("folderA");
executor.scheduleAtFixedRate(folderA, 60,60, TimeUnit.SECONDS);
FolderB folderB = new FolderB("folderB");
executor.scheduleAtFixedRate(folderB, 60,60, TimeUnit.SECONDS);
--and same for Folder C D and E
public static void insideRun(String folderName){
//Contains call to various operations that need to
be perfomed on each file present in Folder A B C D and E
Operation order : Read, Process, Write for each file
}
}
您的问题不清楚,但我猜您希望处理一个文件夹中的文件时不会阻碍或阻止处理其他文件夹中的文件。
多个 ExecutorService
个对象
创建多个 ExecutorService
对象。每个执行程序服务都专注于一个文件夹。如果你有五个文件夹,有五个执行器服务,每个文件夹一个执行器服务。
如果您希望每个文件夹一次只处理一个文件,请将每个执行程序服务设置为单线程。
将您的任务(您的 Runnable
或 Callable
)定义为采用指示要处理哪个文件夹的参数。
public void FileProcessor implements Runnable
{
// Constructor
public FileProcessor( Path path ) { … }
// Implement `Runnable`
@Override
public void run() { … }
}
定义您的文件夹。
List< Path > folders = List.of( pathToA, pathToB, … ) ;
将它们提供给执行程序服务的构造函数。
List< ExecutorService > executorServices = new ArrayList<>() ;
for( Path folder : folders )
{
ExecutorService es = Executors. newSingleThreadExecutor() ;
executorServices.add( es ) ;
es.submit( new FileProcessor( folder ) ) ;
}
然后使用该集合 executorServices
正常关闭所有执行程序服务。
对于预定的执行程序服务,同样的想法。将类型从 ExecutorService
更改为 ScheduledExecutorService
。呼叫Executors.newSingleThreadScheduledExecutor
。将 submit
方法更改为其中一种计划方法。
请注意,即使本答案中提供的解决方案也不能保证所有文件夹都将得到同等的处理。每个执行程序服务将由其自己的线程支持。何时安排线程在 CPU 内核上执行以及执行多长时间取决于主机 OS 和 JVM。
作为 Java 程序员,我们无法直接控制每个线程执行多少工作或执行何种顺序。在运行时,完全有可能文件夹 B 可能处理十几个文件,而文件夹 A 只完成三个文件,而文件夹 C 完成 none。一般来说,您会看到随着时间的推移平均工作量,但短期内可能会有所不同。