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