运行 将 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 从文件中读取 **
保留单个执行器服务,供后续使用
执行程序服务由一个或多个线程池支持。执行者服务的目的是:
- 管理这些线程的创建、过期和调度
- 将您的任务(您的
Runnable
或 Callable
对象)分配给那些线程执行。
所以请随身携带您的 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 结果。
我想按顺序 运行 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 从文件中读取 **
保留单个执行器服务,供后续使用
执行程序服务由一个或多个线程池支持。执行者服务的目的是:
- 管理这些线程的创建、过期和调度
- 将您的任务(您的
Runnable
或Callable
对象)分配给那些线程执行。
所以请随身携带您的 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 结果。