思路
多级反馈队列多用于操作系统或其他存在线程分发工具类对cpu时间片的分发,一般情况下遵循时间耗时短的任务优先执行,耗时较久的任务在后执行且运行时间不超过单位时间片。
代码实现
任务构造类
该类用于模拟需要系统执行的任务,构造方法为该任务名称和工作任务,工作任务在这里用整型int表示,-1表示执行完成一次,若任务执行完毕则返回false表示该任务可以从任务队列中排除。
public class Task{
private int taskWork;
private String name;
public Task(String name,int taskWork){
this.name = name;
this.taskWork = taskWork;
}
public int getTaskWork() {
return taskWork;
}
public String getName() {
return name;
}
public boolean runWork(){
if(this.taskWork>0){
this.taskWork--;
return true;
}
return false;
}
}
任务队列
此处选用阻塞队列作为任务队列,好处在于当队列满了之后入队数据并不会被抛弃,而且阻塞当前线程,直到队列有空间插入为止。
任务队列用于存储Task类,表示需要执行的任务。
public class TaskQueue {
private ArrayBlockingQueue<Task> queue = new ArrayBlockingQueue<Task>(100);
public void addTask(Task task) throws InterruptedException {
this.queue.put(task);
}
public int getQueueSize(){
return this.queue.size();
}
public Task getTask(){
return this.queue.peek();
}
public void finishTask(){
this.queue.poll();
}
}
控制台类
用于处理任务的执行,分发,监控
控制台类构造
此处构造三个任务队列,用于归类存储不同优先级的任务
三个线程:creatWork线程用于创建Task类并分发至各个任务队列。watch线程用于监控各任务队列的任务情况。work线程用于处理各个队列的任务。
private TaskQueue taskQueue1;
private TaskQueue taskQueue2;
private TaskQueue taskQueue3;
private Thread creatWork;
private Thread watch;
private Thread work;
createWork线程
在这里不停随机生成0~300的随机数作为线程工作内容填入三个线程队列。0-100至第一个任务队列,100-200至第二个任务队列,200-300至第三个任务队列。每100ms创建一个任务并入队
Random r = new Random();
int i = 0;
Task t;
while(true){
try {
i = r.nextInt(300);
if(i<100){
t = new Task(i+"任务",i);
taskQueue1.addTask(t);
}else if(100<=i && i<200){
t = new Task(i+"任务",i);
taskQueue2.addTask(t);
}else{
t = new Task(i+"任务",i);
taskQueue3.addTask(t);
}
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
watch线程
监控线程每秒对任务队列进行以此扫描.。
while(true){
try {
System.out.println("------------任务队列1任务数:"+taskQueue1.getQueueSize());
System.out.println("------------任务队列2任务数:"+taskQueue2.getQueueSize());
System.out.println("------------任务队列3任务数:"+taskQueue3.getQueueSize());
System.out.println("---------------------------------------------------");
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
work线程
工作线程用于执行完成任务队列中的任务,优先选取第一队列进行执行,其次第二,最次第三。执行任务由任务队列的peek()方法选取队头但不出队,并执行runWork()方法模拟,每毫秒执行一次Task对象的runWork方法,当对象的taskWork被递减为0时,返回true,此时线程认为该任务已经执行完成并让该任务队列执行poll()方法,将执行执行完的Task对象排除出该队列。
同时定义time变量为50,视为一个单位时间片,每次执行就递减,时间片消耗完或任务执行完都会导致此次runWork()方法执行完成。
private boolean runWork(Task t,String queueName) throws InterruptedException {
int time = 50;
while(t.runWork() && time>=0){
sleep(1);
time--;
}
if(t.getTaskWork()==0){
System.out.println(queueName+"---------------"+t.getName()+"任务执行完成");
return true;
}
if(time<0){
System.out.println(queueName+"---------------"+t.getName()+"时间片用尽,切换任务执行");
}
return false;
}
@Override
public void run() {
Task t = null;
try {
while(true) {
sleep(1);
if (taskQueue1.getQueueSize()>0) {
t = taskQueue1.getTask();
if (runWork(t,"任务队列1")) {
taskQueue1.finishTask();
}
} else if (taskQueue1.getQueueSize()==0 && taskQueue2.getQueueSize()>0) {
t = taskQueue2.getTask();
if (runWork(t,"任务队列2")) {
taskQueue2.finishTask();
}
} else if (taskQueue1.getQueueSize()==0 && taskQueue2.getQueueSize()==0 && taskQueue3.getQueueSize()>0) {
t = taskQueue3.getTask();
if (runWork(t,"任务队列3")) {
taskQueue3.finishTask();
}
} else {
System.out.println("-----------------------任务队列为空");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
测试结果
模拟运行
------------任务队列1任务数:0
------------任务队列2任务数:0
------------任务队列3任务数:0
---------------------------------------------------
任务队列2---------------127任务时间片用尽,切换任务执行
任务队列2---------------127任务时间片用尽,切换任务执行
任务队列2---------------127任务任务执行完成
任务队列2---------------198任务时间片用尽,切换任务执行
任务队列1---------------78任务时间片用尽,切换任务执行
任务队列1---------------78任务任务执行完成
任务队列1---------------84任务时间片用尽,切换任务执行
任务队列1---------------84任务任务执行完成
任务队列1---------------44任务任务执行完成
任务队列1---------------77任务时间片用尽,切换任务执行
任务队列1---------------77任务任务执行完成
任务队列1---------------90任务时间片用尽,切换任务执行
------------任务队列1任务数:1
------------任务队列2任务数:3
------------任务队列3任务数:1
---------------------------------------------------
任务队列1---------------90任务任务执行完成
任务队列2---------------198任务时间片用尽,切换任务执行
任务队列2---------------198任务时间片用尽,切换任务执行
任务队列2---------------198任务任务执行完成
任务队列2---------------138任务时间片用尽,切换任务执行
任务队列2---------------138任务时间片用尽,切换任务执行
任务队列1---------------59任务时间片用尽,切换任务执行
任务队列1---------------59任务任务执行完成
任务队列2---------------138任务任务执行完成
任务队列1---------------18任务任务执行完成
任务队列2---------------133任务时间片用尽,切换任务执行
任务队列2---------------133任务时间片用尽,切换任务执行
任务队列2---------------133任务任务执行完成
任务队列2---------------104任务时间片用尽,切换任务执行
任务队列2---------------104任务任务执行完成
任务队列2---------------104任务时间片用尽,切换任务执行
------------任务队列1任务数:1
------------任务队列2任务数:2
------------任务队列3任务数:5
---------------------------------------------------
任务队列1---------------57任务时间片用尽,切换任务执行
任务队列1---------------57任务任务执行完成
任务队列2---------------104任务任务执行完成
任务队列1---------------59任务时间片用尽,切换任务执行
任务队列1---------------59任务任务执行完成
任务队列2---------------171任务时间片用尽,切换任务执行
任务队列2---------------171任务时间片用尽,切换任务执行
任务队列2---------------171任务时间片用尽,切换任务执行
任务队列2---------------171任务任务执行完成
任务队列2---------------184任务时间片用尽,切换任务执行
任务队列2---------------184任务时间片用尽,切换任务执行
任务队列2---------------184任务时间片用尽,切换任务执行
任务队列2---------------184任务任务执行完成
任务队列2---------------127任务时间片用尽,切换任务执行
任务队列1---------------40任务任务执行完成
任务队列2---------------127任务时间片用尽,切换任务执行
任务队列2---------------127任务任务执行完成
------------任务队列1任务数:0
------------任务队列2任务数:3
------------任务队列3任务数:8
---------------------------------------------------
完整代码
任务类
package multiLevelFeedbackQueer;
public class Task{
private int taskWork;
private String name;
public Task(String name,int taskWork){
this.name = name;
this.taskWork = taskWork;
}
public int getTaskWork() {
return taskWork;
}
public String getName() {
return name;
}
public boolean runWork(){
if(this.taskWork>0){
this.taskWork--;
return true;
}
return false;
}
}
任务队列类
package multiLevelFeedbackQueer;
import java.util.concurrent.ArrayBlockingQueue;
public class TaskQueue {
private ArrayBlockingQueue<Task> queue = new ArrayBlockingQueue<Task>(100);
public void addTask(Task task) throws InterruptedException {
this.queue.put(task);
}
public int getQueueSize(){
return this.queue.size();
}
public Task getTask(){
return this.queue.peek();
}
public void finishTask(){
this.queue.poll();
}
}
控制台类
package multiLevelFeedbackQueer;
import java.util.Random;
public class Console {
private TaskQueue taskQueue1;
private TaskQueue taskQueue2;
private TaskQueue taskQueue3;
private Thread creatWork;
private Thread watch;
private Thread work;
public void start(){
preRun();
creatWork.start();
watch.start();
work.start();
}
private void preRun(){
taskQueue1 = new TaskQueue();
taskQueue2 = new TaskQueue();
taskQueue3 = new TaskQueue();
creatWork = new Thread(){
@Override
public void run() {
Random r = new Random();
int i = 0;
Task t;
while(true){
try {
i = r.nextInt(300);
if(i<100){
t = new Task(i+"任务",i);
taskQueue1.addTask(t);
}else if(100<=i && i<200){
t = new Task(i+"任务",i);
taskQueue2.addTask(t);
}else{
t = new Task(i+"任务",i);
taskQueue3.addTask(t);
}
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
watch = new Thread(){
@Override
public void run() {
while(true){
try {
System.out.println("------------任务队列1任务数:"+taskQueue1.getQueueSize());
System.out.println("------------任务队列2任务数:"+taskQueue2.getQueueSize());
System.out.println("------------任务队列3任务数:"+taskQueue3.getQueueSize());
System.out.println("---------------------------------------------------");
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
work = new Thread(){
private boolean runWork(Task t,String queueName) throws InterruptedException {
int time = 50;
while(t.runWork() && time>=0){
sleep(1);
time--;
}
if(t.getTaskWork()==0){
System.out.println(queueName+"---------------"+t.getName()+"任务执行完成");
return true;
}
if(time<0){
System.out.println(queueName+"---------------"+t.getName()+"时间片用尽,切换任务执行");
}
return false;
}
@Override
public void run() {
Task t = null;
try {
while(true) {
sleep(1);
if (taskQueue1.getQueueSize()>0) {
t = taskQueue1.getTask();
if (runWork(t,"任务队列1")) {
taskQueue1.finishTask();
}
} else if (taskQueue1.getQueueSize()==0 && taskQueue2.getQueueSize()>0) {
t = taskQueue2.getTask();
if (runWork(t,"任务队列2")) {
taskQueue2.finishTask();
}
} else if (taskQueue1.getQueueSize()==0 && taskQueue2.getQueueSize()==0 && taskQueue3.getQueueSize()>0) {
t = taskQueue3.getTask();
if (runWork(t,"任务队列3")) {
taskQueue3.finishTask();
}
} else {
System.out.println("-----------------------任务队列为空");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
}