Java/Android中 队列的实现方案

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版权协议,转载请附上原文出处链接和本声明。