程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用执行器服务顺序运行多个 java 线程大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决使用执行器服务顺序运行多个 java 线程?

开发过程中遇到使用执行器服务顺序运行多个 java 线程的问题如何解决?下面主要结合日常开发的经验,给出你关于使用执行器服务顺序运行多个 java 线程的解决方法建议,希望对你解决使用执行器服务顺序运行多个 java 线程有所启发或帮助;

我想按顺序运行 2 个或更多线程,我的意思是例如:首先它应该运行第一个线程,然后是第二个线程,然后......。 我用过 Executors.newSingleThreadExecutor();也。我有 3 个任务:1-创建一个文件 2-在其中写入一些内容 3-读取文件 创建任务:

 public class FirstTask implements Runnable{
 private CreateRolefile createFIEl = new CreateRolefile();
  @OverrIDe
  public voID run() {
    createFIEl.createfile();
}

}

createfile() 方法:

    public Path createfile(){

    Path path = Paths.get("files/first.txt");

    if (!files.exists(path)) {
        try {
            files.createfile(path);

        } catch (IOException E) {
            System.out.println("something went wrong while creaTing first.txt .Please try again!");
        }
        System.out.println("thread name = "+Thread.currentThread().getname());
        return path;
    } else {
        System.out.println("This file is already exist!!");
        System.out.println("thread name = "+Thread.currentThread().getname());
        return path;
    }
}

SecondTask 类是:

public class SecondTask implements Runnable {
WriteRolefile writefile = new WriteRolefile();

@OverrIDe
public voID run() {
    writefile.Writefile("1020");
}

} 这是我的主要方法:

 public static voID main(String[] args) throws ExecutionException,InterruptedException {
    Executorservice executorservice1 = Executors.newSingleThreadExecutor();
    Runnable firstTask =new FirstTask();
    executorservice1.execute(firstTask);
    executorservice1.shutdown();

   Executorservice executorservice2=Executors.newSingleThreadExecutor();
   Runnable secondTask = new SecondTask();
   executorservice2.submit(secondTask);
    executorservice2.shutdown();

   Executorservice executorservice3 =Executors.newSingleThreadExecutor();
    Callable thirdTask=new ThirdTask();
    executorservice3.submit(thirdTask);
    executorservice3.shutdown();
}

ThirdTask 类是:

public class ThirdTask implements Callable<String> {
ReadRolefile readeer = new ReadRolefile();

@OverrIDe
public String call() {
    String s = readeer.readfile();
    return s;
}

}

readfile() 方法是:

public String readfile() {
    Path path = Paths.get("files/first.txt");
    String s = "";
    try {
        if (files.size(path) == 0) {
            System.out.println("nothing has been wrote yet .");
        } else {
            try {
                BufferedReader bufferedReader = files.newBufferedReader(path);
                s = bufferedReader.readline();
            } catch (IOException E) {
                e.printstacktrace();
            }
        }
    } catch (IOException E) {
        e.printstacktrace();
    }
    System.out.println("thread name = " + Thread.currentThread().getname());
    System.out.println(s);
   return s;
}

输出是: 这个文件已经存在!! 线程名称 = pool-1-thread-1 线程名称 = pool-3-thread-1 无效的 线程名称 = pool-2-thread-1

**我需要首先运行 pool-1-thread-1 和 pool-2-thread-1,因为它必须先在文件中写入一个数字,然后 pool-3-thread1 才能从文件中读取 * *

解决方法

保持一个单一的执行器服务,以供连续使用

一个执行器服务由一个或多个线程池支持。执行器服务的目的是:

  • 管理这些线程的创建、到期和调度
  • 将您的任务(您的 RunnableCallable 对象)分配给这些线程执行。

因此,请保留您的 Executorservice 对象。您正在创建新的,然后关闭它们。如果你想连续运行三个任务,只使用一个执行器服务。

Executorservice es = Executors.newSingleThreadExecutor();

Runnable task1 = new FirstTask();
es.execute( task1 );

Runnable task2 = new SecondTask();
es.execute( task2 );

Runnable task3 = new ThirdTask();
es.execute( task3 );

es.shutdown();              // Disallow any more tasks to be submitted.
es.awaitTermination( … ) ;  // Wait for submitted tasks to be done/canceled/failed.

您的多个执行程序服务对象出现看似疯狂的行为的原因是,当 CPU 内核上的执行时间无法预测时,哪个执行程序服务获得了多少执行时间。您的第二个 executor 服务可能首先启动,但在其工作中途暂停。同时第三个执行器服务可以开始和完成它的工作,甚至在第一个执行器服务开始工作之前。

每次运行您的应用程序时,从前到后到第三次运行的顺序以及以什么顺序完成的顺序都会有所不同。 CPU 内核上的任务调度是根据 JVM 和主机操作系统的突发奇想完成的,随运行时的瞬时条件而变化。

如果您希望在单个后台线程上按顺序完成一系列任务,请使用单个 newSingleThreadExecutor() 对象来分配所有这些任务。

,

这可能不是您问题的确切答案。
我们可以使用如下所示的标志来控制线程的执行。
执行顺序 Thread1 --> Thread2 --> Thread3 总是。

import com.google.common.collect.Lists;

import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executorservice;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

AtomicBoolean flag1 = new AtomicBoolean@R_874_5279@; // to inDicate Thread1 completed execution
AtomicBoolean flag2 = new AtomicBoolean@R_874_5279@; // to inDicate Thread2 completed execution
final CopyOnWriteArrayList<String> result = new CopyOnWriteArrayList<>(); // thread safe collection just to capture results from threads

Callable<Void> r1 = () -> {
    result.add("Thread1 : " + Thread.currentThread().getName());
    flag1.set(true);
    return null;
};

Callable<Void> r2 = () -> {
    while (!flag1.get()) {
        System.out.println("thread2 waiTing");
    }
    result.add("Thread2 : " + Thread.currentThread().getName());
    flag2.set(true);
    return null;
};

Callable<Void> r3 = () -> {
    while (!flag2.get()) {
        System.out.println("thread3 waiTing");
    }
    result.add("Thread3 : " + Thread.currentThread().getName());
    return null;
};

// using same executor service for all the threads as suggested from this answer: https://stackoverflow.com/a/67069903/2987755
Executorservice ec = Executors.newCachedThreadPool();

// call all the threads
ec.invokeAll(Lists.newArrayList(r1,r2,r3));

// we do not need Executorservice anymore so shutTing it down
ec.shutdown();

// print results
System.out.println(result);


//output
// truncated system out waiTing log
//[Thread1 : pool-1-thread-1,Thread2 : pool-1-thread-2,Thread3 : pool-1-thread-3]

,

当您按顺序执行三项任务时,您只需要一个 Executorservice 和一个 thread。提交所有任务,等待结果:

String filename = "e:\\temp.txt";
Callable<Path> createTask = ()->{System.out.println("File created"); return Path.of(fileName);}; 
Runnable writeTask = ()->{System.out.println("Written to the file"); /*put write code here*/};
Callable<String> readTask = ()->{System.out.println("Reading from the file"); return "fileData 1020";};

Executorservice es = Executors.newSingleThreadExecutor();
es.submit(createTask);
es.execute(writeTask);
Future<String> f = es.submit(readTask);

es.shutdown();
String data = f.get(); //wait for readTask to finish then get data
System.out.println("Read Data is: " + data);

输出:

File created
Written to the file
Reading from the file
Read Data is: fileData 1020

这里我使用 lambdas 来定义任务以保持简单。
Executorservice 维护所有登顶任务的队列。由于我们在此服务中只有一个线程,因此所有任务都会以先进先出的方式一一执行。
此外,我们正在使用 Future<String> 对象来检索文件读取结果。 Future#get() 等待任务完成,然后返回结果。

@H_696_117@

大佬总结

以上是大佬教程为你收集整理的使用执行器服务顺序运行多个 java 线程全部内容,希望文章能够帮你解决使用执行器服务顺序运行多个 java 线程所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:线程