package com.bisien.test.application;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Queen {
public static void main(String[] args) {
System.out.println("--------------------- " + Thread.currentThread().getName());
// 这里暂时只开一个窗口。
TaskQueue taskQueue = new TaskQueue(1);
taskQueue.start();
for (int i = 0; i < 10; i++) {
PrintTask task = new PrintTask(i);
taskQueue.add(task);
}
// 队里的打印状况按照我们理想的状态打印出来了
// 我的id是:0 ThreadName :Thread-0
//我的id是:1 ThreadName :Thread-0
//我的id是:2 ThreadName :Thread-0
//我的id是:3 ThreadName :Thread-0
//我的id是:4 ThreadName :Thread-0
//我的id是:5 ThreadName :Thread-0
//我的id是:6 ThreadName :Thread-0
//我的id是:7 ThreadName :Thread-0
//我的id是:8 ThreadName :Thread-0
//我的id是:9 ThreadName :Thread-0
// 如果开启多个窗口的话,第一个买票人,去第一个窗口买票,第二个人去第二个窗口买票,第三个人去第三个窗口买票,第四个人进去排在第一位,
// 当第一、第二、第三、窗口中不论哪一个窗口办完事后(假设买票),第四个人就去那个窗口办事(假设买票),第五个人等待,一次类推,这样子就
// 达到队列同时并发三个任务的效果
// 上面这个就是一个普通队列,其他一些特性也就是在此基础上进行封装的,那么下面我就在此基础上加上任务优先级,也就说我们说的特殊窗口---> 军人优先
}
public static class PrintTask implements ITask{
private int id;
public PrintTask(int id) {
this.id = id;
}
public void run() {
// 为了尽量模拟窗口办事的速度,我们这里停顿两秒。
try {
Thread.sleep(2000);
} catch (InterruptedException ignored) {
}
System.out.println("我的id是:" + id + " ThreadName :" + Thread.currentThread().getName());
}
}
// 办事的人(假设购买火车票)
public interface ITask {
// 具体要办的事
void run();
}
// 窗口(火车站窗口),也就是给买火车票的人办事
public static class TaskExecutor extends Thread {
// 窗口排的队,这个对队里面全是买火车票的人
private BlockingQueue<ITask> taskQueue;
// 判断当前窗口是否开放,true 表示开放
private boolean isRunning = true;
public TaskExecutor(BlockingQueue<ITask> taskQueue) {
this.taskQueue = taskQueue;
}
@Override
public void run() {
while (isRunning) {
ITask iTask;
try {
iTask = taskQueue.take();//叫下一个人进来买票
// take() 当队列中的item为空的时候,它会一直处于阻塞状态,当队列中的进入item的时候,他会立即返回一个值
// (所以我们把它放入到一个Thread 中,以避免阻塞调用它的线程,Android中可能是ui线程)
} catch (InterruptedException e) {
e.printStackTrace();
if (!isRunning) {
// 发生意外,并且如果窗口已经关闭,
interrupt();
break;
}
// 发生意外,不是窗口还是开着(也就是营业的状态)
continue;//那么久继续等待
}
// 为这个人买票
iTask.run();
// 退出当前线程
// quit();
}
}
// 下班
public void quit() {
isRunning = false;
interrupt();
}
}
// 办事的人(买票人)和窗口都有了(火车站售票窗口),我们封装一个队列,某机构
public static class TaskQueue {
// 某机构排的队,队里买火车票的人
private BlockingQueue<ITask> mTaskQueue;
// 好多窗口
private TaskExecutor[] mTaskExecutors;
// 在开发者new队列的时候,要指定窗口数量。
public TaskQueue(int size) {
mTaskQueue = new LinkedBlockingQueue<>();// 如果开启多个窗口的的话,共享一群人
mTaskExecutors = new TaskExecutor[size];
}
// 开始上班
public void start() {
stop();//开启之前先停止
// 把各个窗口都打开,让窗口开始上班。
for (int i = 0; i < mTaskExecutors.length; i++) {
// 创建n 条线程,然后开启
mTaskExecutors[i] = new TaskExecutor(mTaskQueue);
mTaskExecutors[i].start();
}
}
public void stop() {
if (mTaskExecutors != null){
for (TaskExecutor taskExecutor : mTaskExecutors) {
if (taskExecutor != null) taskExecutor.quit();
}
}
}
public <T extends ITask> int add(T task){
if(!mTaskQueue.contains(task)){
mTaskQueue.add(task);
}
// 返回排的队的人数,公开透明,让外面的人看的有多少人在等着办事。
return mTaskQueue.size();
}
}
}
------------------------------------------------------下面是实现队列的优先级----------------------------------------------------
package com.bisien.test.application;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
//优先级队列
public class PriorityQueen {
public static void main(String[] args) {
System.out.println("--------------------- " + Thread.currentThread().getName());
// 如果开启多个窗口的话,第一个买票人,去第一个窗口买票,第二个人去第二个窗口买票,第三个人去第三个窗口买票,第四个人进去排在第一位,
// 当第一、第二、第三、窗口中不论哪一个窗口办完事后(假设买票),第四个人就去那个窗口办事(假设买票),第五个人等待,一次类推,这样子就
// 达到队列同时并发三个任务的效果
// 上面这个就是一个普通队列,其他一些特性也就是在此基础上进行封装的,那么下面我就在此基础上加上任务优先级,也就说我们说的特殊窗口---> 军人优先
TaskQueue taskQueue = new TaskQueue(1 );
taskQueue.start();
// 为了显示出优先级效果,我们预添加3个在前面堵着,让后面的优先级效果更明显。
taskQueue.add(new PrintTask(110));
taskQueue.add(new PrintTask(112));
taskQueue.add(new PrintTask(122));
for (int i = 0; i < 10; i++) {
PrintTask task = new PrintTask(i);
if (1 == i) {
task.setPriority(Priority.LOW); // 让第2个进入的人最后办事。
} else if (8 == i) {
task.setPriority(Priority.HIGH); // 让第9个进入的人第二个办事。
} else if (9 == i) {
task.setPriority(Priority.Immediately); // 让第10个进入的人第一个办事。
}
taskQueue.add(task);
}
}
public static class PrintTask implements ITask {
// 默认优先级。
private Priority priority = Priority.DEFAULT;
private int id;
public PrintTask(int id) {
this.id = id;
}
public void run() {
// 为了尽量模拟窗口办事的速度,我们这里停顿两秒。
try {
Thread.sleep(2000);
} catch (InterruptedException ignored) {
}
System.out.println("我的id是:" + id + " ThreadName :" + Thread.currentThread().getName());
}
@Override
public void setPriority(Priority priority) {
this.priority = priority;
}
@Override
public Priority getPriority() {
return priority;
}
private int sequence;
@Override
public void setSequence(int sequence) {
this.sequence = sequence;
}
@Override
public int getSequence() {
return sequence;
}
@Override
public int compareTo(ITask another) {
final Priority me = this.getPriority();
final Priority it = another.getPriority();
// System.out.println("me : " + me.name() + "---------it :" + it.name() + " -----id : " + id);
// compareTo(E)中传进来的E是另一个Task,如果当前Task比另一个Task更靠前就返回负数,如果比另一个Task靠后,那就返回正数,如果优先级相等,那就返回0。
// return me == it ? this.getSequence() - another.getSequence() : it.ordinal() - me.ordinal();
// 返回的数是0代表两个元素相同,正数说明大于,负数说明小于
return me == it ? 0 : it.ordinal() - me.ordinal();
}
}
// 我们首先让task 有一个优先级的标识,所以我用一个枚举类,来标记优先级
public enum Priority {
LOW,//最低
DEFAULT,//默认级别
HIGH,//高于默认级别
Immediately //立刻执行
}
// 办事的人(假设购买火车票),这个等级肯定要给我们办事的人,也就是Task
public interface ITask extends Comparable<ITask> {
//具体要办的事
void run();
void setPriority(Priority priority);
Priority getPriority();
void setSequence(int sequence);
int getSequence();
}
// 窗口(火车站窗口),也就是给买火车票的人办事
public static class TaskExecutor extends Thread {
// 窗口排的队,这个对队里面全是买火车票的人
private BlockingQueue<ITask> taskQueue;
// 判断当前窗口是否开放,true 表示开放
private boolean isRunning = true;
public TaskExecutor(BlockingQueue<ITask> taskQueue) {
this.taskQueue = taskQueue;
}
@Override
public void run() {
while (isRunning) {
ITask iTask;
try {
iTask = taskQueue.take();//叫下一个人进来买票
// take() 当队列中的item为空的时候,它会一直处于阻塞状态,当队列中的进入item的时候,他会立即返回一个值
// (所以我们把它放入到一个Thread 中,以避免阻塞调用它的线程,Android中可能是ui线程)
} catch (InterruptedException e) {
e.printStackTrace();
if (!isRunning) {
// 发生意外,并且如果窗口已经关闭,
interrupt();
break;
}
// 发生意外,不是窗口还是开着(也就是营业的状态)
continue;//那么久继续等待
}
// 为这个人买票
iTask.run();
// 退出当前线程
// quit();
}
}
// 下班
public void quit() {
isRunning = false;
interrupt();
}
}
// 办事的人(买票人)和窗口都有了(火车站售票窗口),我们封装一个队列,某机构
public static class TaskQueue {
// 某机构排的队,队里买火车票的人
private BlockingQueue<ITask> mTaskQueue;
// 好多窗口
private TaskExecutor[] mTaskExecutors;
//
private AtomicInteger mAtomicInteger = new AtomicInteger();
// 在开发者new队列的时候,要指定窗口数量。
public TaskQueue(int size) {
// 这里我们需要把LinkedBlockingQueue 替换成PriorityBlockingQueue<E> 因为它可以自动做到优先级的比较,
// 也就是我们的Task必须要实现 Comparable<E> 接口
mTaskQueue = new PriorityBlockingQueue<>();// 如果开启多个窗口的的话,共享一群人
mTaskExecutors = new TaskExecutor[size];
}
// 开始上班
public void start() {
stop();//开启之前先停止
// 把各个窗口都打开,让窗口开始上班。
for (int i = 0; i < mTaskExecutors.length; i++) {
// 创建n 条线程,然后开启
mTaskExecutors[i] = new TaskExecutor(mTaskQueue);
mTaskExecutors[i].start();
}
}
public void stop() {
if (mTaskExecutors != null) {
for (TaskExecutor taskExecutor : mTaskExecutors) {
if (taskExecutor != null) taskExecutor.quit();
}
}
}
public <T extends ITask> int add(T task) {
if (!mTaskQueue.contains(task)) {
// mAtomicInteger.incrementAndGet() 每次都会自增一,相当于这个方法:mAtomicInteger.addAndGet(1);
task.setSequence(mAtomicInteger.incrementAndGet()); // 注意这行。
mTaskQueue.add(task);
}
// 返回排的队的人数,公开透明,让外面的人看的有多少人在等着办事。
return mTaskQueue.size();
}
}
}
参考:https://blog.csdn.net/u012062455/article/details/78247234
版权声明:本文为weixin_39413778原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。