一、流水线
1、流水线简述
简单来说,流水线是将一个复杂庞大的任务拆解为若干个小而简单的任务并依次执行,并且把当前任务的输出值作为下一个任务的输入值,通过每个阶段相应的工作者线程去执行。通过java创建出来的流水线任务可以大幅提高任务的执行效率以及速度,并且可以缩短任务的执行时间。
2、图示
3、优点
充分利用CPU,提高其计算效率。
允许子任务间存在依赖关系的条件下实现并行计算。
非常便于采用单线程模型实现对子任务的处理。
二、流水线创建
1、流水线任务创建
类比现实中的流水线,我们需要一个执行方案和一个任务列表。其中执行方案说明了流水线的执行步骤,即说明每个步骤该做什么。另一个是任务列表,其中保存了需要被执行的任务。接下来将创建三个简单的流水线任务。
public class Task {
//设置任务的初始值
int calNum = 5;
//设置任务执行信号
boolean exe1 , exe2 , exe3;
public boolean step1(){
//步骤1的判断信号为false时开始执行
if(!exe1){
calNum += 12;
//执行完毕后判断信号改为true
exe1 = true;
return exe1;
}
//当步骤1未被执行时返回false
return false;
}
public boolean step2(){
if(exe1 && !exe2){
calNum += 5;
exe2 = true;
return exe2;
}
return false;
}
public boolean step3(){
if(exe2 && !exe3){
calNum -= 3;
exe3 = true;
return exe3;
}
return false;
}
}
这里创建的类不仅是流水线的执行步骤,同时也是任务类表的数据结构。添加判断条件的原因是由于线程启动并不会按照顺序进行,因此添加判断信号用于检测当前任务是否执行完毕,以及能否执行下一个程序,并且保证任务是按规定的顺序执行。
2、创建任务列表
任务列表的创建是一个独立的过程,因此在创建任务类表类时,需要通过一个线程去启动。当创建完毕后,基本的流水线准备阶段就已经完成。列表中的每一个对象即为一个流水线。
public class TaskCreate implements Runnable{
//创建一个空的流水线列表。
ArrayList<Test6.Task> taskList = null;
//创建构造器
public TaskCreate(ArrayList taskList){
this.taskList = taskList;
}
@Override
public void run() {
//通过for循环在列表中生成100个流水线任务
for (int i = 0; i < 100; i++) {
//初始化流水线执行过程。
Task task = new Task();
//将初始化的对象添加到任务列表中
taskList.add(task);
}
}
}
3、创建工作者线程
创建工作者线程的目的是让流水线的每一个步骤都能够独立执行,加上流水线中设置好的信号控制,这样就实现了流水线步骤独立并且按顺序执行。因此,需要创建三个流水线的线程用于控制三个步骤。
public class WorkThread implements Runnable {
//定义任务列表对象
ArrayList<Test6.Task> taskList;
//构造器生成,用于接受任务列表
public WorkThread(ArrayList taskList){
this.taskList = taskList;
}
@Override
public void run() {
//保持流水线运行状态
while (true){
//设置休眠时间
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//设置流水线执行完毕的判断条件
int count = 0;
for (int i = 0; i < taskList.size(); i++) {
//设置流水线对象并执行
Test6.Task task = taskList.get(i);
task.step1();
if(task.exe1){
//执行成功后判断条件加1
count ++;
}
}
//执行完列表中所有任务后停止
if(count == 100){
System.out.println("T1执行完毕");
break;
}
}
}
}
class WorkThread02 implements Runnable{
ArrayList<Task> taskList;
public WorkThread02(ArrayList taskList){
this.taskList = taskList;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int count = 0;
for (int i = 0; i < taskList.size(); i++) {
Test6.Task task = taskList.get(i);
task.step2();
if(task.exe2){
count++;
}
}
if(count == 100){
System.out.println("T2执行完毕");
break;
}
}
}
}
class WorkThread03 implements Runnable {
ArrayList<Task> taskList;
public WorkThread03(ArrayList taskList){
this.taskList = taskList;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int count = 0;
for (int i = 0; i < taskList.size(); i++) {
Test6.Task task = taskList.get(i);
task.step3();
if(task.exe3){
count ++;
}
}
if(count == 100){
System.out.println("T3执行完毕");
break;
}
}
}
}
4、主程序创建
通过主程序启动流水线
public class Manage {
public static void main(String[] args) {
//初始化任务列表
ArrayList<Task> taskList = new ArrayList<>();
//初始化流水线任务创建对象
Test6.TaskCreate taskCreate = new TaskCreate(taskList);
//通过线程启动任务创建对象
Thread creator = new Thread(taskCreate);
creator.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//初始化工作者线程对象
WorkThread workThread = new WorkThread(taskList);
WorkThread02 workThread02 = new WorkThread02(taskList);
WorkThread03 workThread03 = new WorkThread03(taskList);
//通过线程启动工作者线程,并启动流水线中的三个方法
Thread t1 = new Thread(workThread);
Thread t2 = new Thread(workThread02);
Thread t3 = new Thread(workThread03);
t1.start();
t2.start();
t3.start();
//设置线程执行顺序
try {
creator.join();
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//现实执行结果
for (int i = 0; i < taskList.size(); i++) {
System.out.println(taskList.get(i).calNum);
}
}
}
5、运行结果
从Task类中的定义可以简单计算出,该流水线执行完毕后结果为19,如果在执行过程中其中有值没有为19说明执行顺序有问题
T1执行完毕
T2执行完毕
T3执行完毕
19
19
19
19