The practice of priority task queues in Java/android __java

Source: Internet
Author: User
Tags comparable int size

Copyright NOTICE: Reprint must note this article to be transferred from Zhangjie's blog: http://blog.yanzhenjie.com

Just finished the company's work, to the group of water, a few friends asked me how to achieve the queue, so I write a bar. This article applies to Java and Android developers, from implementing one of the simplest queues to implementing a prioritized queue, and you'll be able to master the basics of queue principles. Basic understanding of queues

Use a scene in life to lift a chestnut, a period of time very popular TV series "The name of the people" there is a Ding Yijien-style window We should all know, we do not say "the name of the people" do not say Ding Yijien, we say this window.

We know that during work in an organization , the window has always been open, someone to work the window began to do things, no one to do the window is in the waiting state, if the person to do more, these people must queue up (I particularly hate in the line of the place do not queue people, Appeal to everyone if it is not a vital emergency, must queue, who do not want to do it earlier, the window may be multiple, and these windows may have some special windows, such as military priority.

Say the queue before saying two nouns: task is mission, Taskexecutor is task executor.

and the queue we're talking about today is exactly the case of an organization , where the queue starts executing tasks immediately when a task comes in, and Taskexecutor is in a blocking state when there are no tasks, taskexecutor. When there are many tasks, tasks also need to be queued, taskexecutor can be multiple, and you can specify a few tasks to be executed first or behind.

In summary, we come to a relationship where the queue is equivalent to an organization , thetaskexecutor is the window , and the person is the task.

This article source code download address:
http://download.csdn.net/detail/yanzhenjie1003/9841188
Project source code is written with idea, you can import it directly to your idea, or copy the source directly to eclipse or Androidstudio. normal Queues

Of course, many organizations do not have a military priority window, so there are queues with no priority, so we first implement a low-priority queue.

Our common queue interfaces are:queue<e>, BLOCKINGQUEUE<E>, and based on the features we have described above, we use blockingqueue<e> to implement task queues,blockingqueue< There are many implementations of e>, and here we choose Linkedblockingqueue<e>.

Unlike one of the institutions mentioned above, an institution can be preceded by an organization, a window, and a business person. But when we write code, want to write a queue, so be sure to write taskexecutor in the queue, then you have to write a good taskexecutor class, and so on have to have a task class first.

So we first write a task interface, which is the person who does it, and I design it as an interface to facilitate people in different kinds of things:

The people who do things. Public
interface ITask {

    //affairs, we put the way of doing things to the people, that is, what you want to do, by your own decision.
    void Run ();
}

Next, write a Taskexecutor class, which is a window that executes a task, looks at the annotation carefully and helps to understand:

//Window public class Taskexecutor extends Thread {//In the window of the team, the team inside is the person.

    Private blockingqueue<itask> Taskqueue;
    Whether the window is waiting for a job.

    Private Boolean isrunning = true;
    Public Taskexecutor (blockingqueue<itask> taskqueue) {this.taskqueue = Taskqueue;
    }//Off duty.
        public void Quit () {isrunning = false;
    Interrupt ();
            @Override public void Run () {while (isrunning) {//If it is working state.
            ITask ITask;
            try {iTask = Taskqueue.take ();//Ask the next person to come in, no one will wait.
                    catch (Interruptedexception e) {if (!isrunning) {//unexpected, close the window if it is off duty.
                    Interrupt (); Break
                If you execute to break, the following code will not work.
                //unexpected, not off duty, then the window continues to wait.
            Continue
            //For the person doing the work.
        Itask.run (); }
    }
}

Here's a little bit of explanation for the blockingqueue<t> #take () method, which will always be blocked when the item in the queue is empty, and it will immediately have a return value when the item is entered in the queue. It's just like the Serversocket.accept () method, so we put it in a thread to avoid blocking the threads that call it (Android may be the main thread).

The people and the windows are all there, and we encapsulate a queue, which is an organization , to manage these windows:

An institution.
    public class Taskqueue {//The team in the queue, the team is the person in the office.
    Private blockingqueue<itask> Mtaskqueue;
    Many windows.

    Private taskexecutor[] mtaskexecutors;
    In the developer new queue, specify the number of Windows.
        public taskqueue (int size) {mtaskqueue = new linkedblockingqueue<> ();
    Mtaskexecutors = new Taskexecutor[size];
    //start work.
        public void Start () {Stop ();
        Open each window and let the window start to work.
            for (int i = 0; i < mtaskexecutors.length i++) {mtaskexecutors[i] = new Taskexecutor (mtaskqueue);
        Mtaskexecutors[i].start ();
    }//unify each window to work.
                public void Stop () {if (mtaskexecutors!= null) for (Taskexecutor taskexecutor:mtaskexecutors) {
            if (taskexecutor!= null) taskexecutor.quit ();
    Open a door so that the person who handles the work can come in. Public <t extends itask> int Add (T Task) {if (!mtaskqueue.contains (Task)) {Mtaskqueue.add (Task
        ); }
        //The number of teams returning to the platoon is open and transparent, letting people see how many people are waiting to act.
    return Mtaskqueue.size (); }
}

An organization, a window, a person to do the work, we will send a person to go to a specific matter, but the above my task is an interface, so we need to use a class to implement this interface, to do something:

Do something to print your own ID. Public
class Printtask implements ITask {

    private int id;

    public printtask (int id) {
        this.id = ID;
    }

    @Override public
    Void Run () {
        //To try to simulate the speed of the window, we pause for two seconds.
        try {
            thread.sleep;
        } catch (Interruptedexception ignored) {
        }

        System.out.println (" My ID is: "+ ID);
    }
}

Now let's simulate the virtual world run once:

public class Main {public

    static void Main (String ... args) {
        //Here only opens one window for the time being.
        taskqueue taskqueue = new Taskqueue (1);
        Taskqueue.start ();

        for (int i = 0; i < i++) {
            printtask task = new Printtask (i);
            Taskqueue.add (Task);}}

Yes, the queues are printed in our ideal condition:

My ID is: 0 my ID is: 1 ID is: 2 my id is: 3 my id is: 4 my id is: 5 my id is: 6 my ID is: 7
my id is:
8 My ID is: 9

Above my door only opened a window, below I open a few more windows:

public class Main {public

    static void Main (String ... args) {
        //Open three windows.
        taskqueue taskqueue = new Taskqueue (3);
        Taskqueue.start (); An institution began to work.

        for (int i = 0; i < i++) {
            //new 10 people who need to act, and go into an organization.
            printtask task = new Printtask (i);
            Taskqueue.add (Task);}}

To illustrate this, we opened 3 windows at initialization time, which should be the order of the Interior:

When the door of an institution is opened, the first person to go into the first window, the second person went into the second window, the third person went into the third window, the fourth person to go in line in the first place, when the first, second, In the third window, no matter which window is done, the fourth person goes to which window to continue the work, the fifth person waits, an analogy. This achieves the effect of three tasks that the queue colleague is concurrent with.

This is a normal queue, some other features are also based on this again encapsulated, then I will be based on this again put the priority of the characters, that is, we said above the special window-> military priority. Priority Queues

When we were waiting in line to do things, we came to a person who acted, so how can we judge if this person is a priority? That is to determine whether it has a priority or even how much he can prioritize.

So we need to have a flag for this task, which is priority, so I tag the priority with an enumeration class:

public enum Priority {
    low,//lowest.
    defaults,//default level. High
    ,//higher than the default level.
    Immediately//immediate execution.
}

Here I have divided four levels: the lowest, the default, the high, immediately, this level is sure to give to our people, that is task:

Public interface ITask {

    void Run ();

    void SetPriority (Priority Priority);

    Priority getpriority ();
}

You can set priorities and get priorities.

We're going to replace the above linkedblockingqueue with Priorityblockingqueue<e>, because it can automatically prioritize comparisons that require generic <e> That is, our task must implement the Comparable<e> interface, and Comparable<e> has a CompareTo (E) method to compare two <T>, so our queues need to change the way they are implemented:

An institution. Public
class Taskqueue {

    //the team in the queue, the team is the person in the office.
    private blockingqueue<itask> mtaskqueue;
    Many windows.
    private taskexecutor[] mtaskexecutors;

    In the developer new queue, specify the number of Windows. Public
    taskqueue (int size) {
        mtaskqueue = new priorityblockingqueue<> ();
        Mtaskexecutors = new Taskexecutor[size];
    }

    ...

The ITask interface then inherits the Comparable<e> interface:

Public interface ITask extends comparable<itask> {

    void Run ();

    void SetPriority (Priority Priority);

    Priority getpriority ();
}

Because of the setpriority (Priority) method and the GetPriority () method and the Comparable<e> CompareTo (E) method, each of our tasks needs to implement these methods, which can be cumbersome, So we encapsulate a basictask:

Public abstract class Basictask implements ITask {

    //default priority.
    private Priority Priority = Priority.default;

    @Override public
    void SetPriority (Priority Priority) {
        this.priority = Priority;
    }

    @Override public
    Priority getpriority () {return
        Priority;
    }

    Make a priority comparison.
    @Override public
    int CompareTo (ITask another) {
        final Priority me = this.getpriority ();
        Final Priority it = another.getpriority ();
        return me = = it? [...] : It.ordinal ()-me.ordinal ();
    }
}

The other is to say, we see CompareTo (E) method does not quite understand, here is the method:

E in CompareTo (e) is another task that returns a negative number if the current task is higher than the other task and returns a positive number if it is more than the other task, and returns 0 if the priority is equal.

In particular, we see that the Priority.orinal () method is invoked when two task priorities are different, and there is a orinal minus the current orinal. The first thing to understand is the priority.orinal () method, which has this method in every enumeration value in Java, and the value of this enumeration is its subscript +1, which is [index + 1], so the priority class we write can actually understand this:

public enum Priority {
    1,
    2,
    3,
    4
}

To continue, if the current task is lower and the task set in CompareTo (E) is given a higher priority, then priority is not the same, then the return value is an integer . Therefore, the current task will be priorityblockingqueue<e> to the back, and if so the return result will be replaced.

but we notice that me = = it? [...] : It.ordinal ()-me.ordinal (); What the hell. Because there is a lack of code here hahaha (this author how silly), this piece of code means when the priority level of the same time what to do, that is, who first joined the queue who went to the front, then how to return the value, how do we know which task to join the queue first. This time the cute I showed up and I gave it a sequence mark when it's time to join the queue, we can modify the ITask interface to add two more methods:

Public interface ITask extends comparable<itask> {

    void Run ();

    void SetPriority (Priority Priority);

    Priority getpriority ();

    void setsequence (int sequence);

    int getsequence ();
}

We use setsequence (int) to mark the order in which it joins the queue, and then because setsequence (int) and getsequence () are all tasks that need to be implemented, we implement these two methods in Basictask:

public abstract class Basictask implements ITask {//default priority.
    Private Priority Priority = Priority.default;

    private int sequence;
    @Override public void SetPriority (Priority Priority) {this.priority = Priority;
    @Override public Priority getpriority () {return Priority;
    @Override public void setsequence (int sequence) {this.sequence = sequence;
    @Override public int getsequence () {return sequence;
    //Make a priority comparison.
        @Override public int CompareTo (ITask another) {final Priority me = this.getpriority ();
        Final Priority it = another.getpriority ();  return me = = it?
    This.getsequence ()-Another.getsequence (): It.ordinal ()-me.ordinal (); }
}

See, just now [...] has become this.getsequence ()-another.getsequence (), which requires a logical correspondence with the above it.ordinal ()-me.ordinal (), which says that if you give the current task a lower Setting the task in CompareTo (E) is a higher priority, then priority is not the same, then the returned value is an integer , so the current task is priorityblockingqueue<e> to the back, If the exchange then return the result will be replaced.

The logic here is the opposite of the logic above, because this is where two priority returns, above the two priority returns, so when the priority is the same, returning a negative number indicates that the current task is in front of it, and returning a positive number indicates that the current task is in the back, just above the logical counterpart.

The next step is to set the sequence for the task, so we do it in the taskqueue of the T Void Add (t) method:

public class Taskqueue {

    private Atomicinteger Matomicinteger = new Atomicinteger ();

    ...

    public taskqueue (int size) {
        ...
    }

    public void Start () {
        ...
    }

    public void Stop () {
        ...
    }

    Public <t extends itask> int Add (T Task) {
        if (!mtaskqueue.contains (Task)) {
            task.setsequence ( Matomicinteger.incrementandget ()); Pay attention to this line.
            Mtaskqueue.add (Task);
        }
        return Mtaskqueue.size ();
    }

Here we use the Atomicinteger class, and its Incrementandget () method increments by 1 each time, in fact it is equivalent to:

Matomicinteger.addandget (1);

Other specific uses, please search, no longer repeat here.

So far, our priority queues are complete and we'll do the testing:

public static void Main (String ... args) {
    //Open a window, which makes the priority more obvious.
    taskqueue taskqueue = new Taskqueue (1);
    Taskqueue.start ();  //An organization to start work.

    //In order to show the priority effect, we add 3 to the front block, so that the next priority effect more obvious.
    Taskqueue.add (new printtask);
    Taskqueue.add (New Printtask (112));
    Taskqueue.add (New Printtask (122));

    for (int i = 0; i < i++) {//starting from No. 0 person.
    printtask task = new Printtask (i);
    if (1 = i) { 
        task.setpriority (priority.low);//Let the 2nd person in the last act.
    else if (8 = i) {
        task.setpriority (Priority.high);//Let the 9th person enter the second act.
    else if (9 = i) {
        task.setpriority (priority.immediately);//Let the 10th man enter the first act.
    } 
    // ... Other incoming people, follow the order of entry.
    Taskqueue.add (Task);
}

Yes, that's the effect we see:

My ID is: 9 my id is: 8 my id is: my ID is: 112 my ID is: 122 my ID is: 0 my id is:
2
my ID is: 3
My ID is: 4
my ID is: 5 my id is: 6 my id is:
7
My id is: 1

Here is the end of this article source download address:
http://download.csdn.net/detail/yanzhenjie1003/9841188
Project source code is written with idea, you can import it directly to your idea, or copy the source directly to eclipse or Androidstudio.

Copyright NOTICE: Reprint must note this article to be transferred from Zhangjie's blog: http://blog.yanzhenjie.com

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.