运行 将 java 线程按顺序与执行程序服务相乘

Run multiple java thread sequentially with executer Services

我想按顺序 运行 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 class 是:

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();
}

第三个任务 class 是:

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 核心上哪个执行程序服务获得多少执行时间是不可预测的。您的第二个执行程序服务可能首先启动,但在其工作中途被暂停。同时,第三个执行器服务可能会开始和完成它的工作,甚至在第一个执行器服务开始它的工作之前。

每次你 运行 你的应用程序,其顺序是第一-第二-第三,以及完成的顺序,都会有所不同。 CPU 核心上的任务调度是由 JVM 和主机 OS 随心所欲完成的,根据 运行 时间的瞬时条件而变化。

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

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

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(false); // to indicate Thread1 completed execution
AtomicBoolean flag2 = new AtomicBoolean(false); // 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: 
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

这里我使用 lambda 来定义任务以保持简单。
ExecutorService 维护所有已提交任务的队列。由于我们在该服务中只有一个线程,因此所有任务将以先进先出的方式一个接一个地执行。
我们还使用 Future<String> 对象来检索文件读取结果。 Future#get() 等待任务完成,然后 returns 结果。