Ahem, fat hau recently…

Ali met with a written test topic, although the topic is not very difficult, but for the usual lax practice of the fat trench, or spent some time.

Today, I will take some time to sort it out, so that we can be handy when we encounter such questions.

Write a multithread, 3 threads, the first thread prints One, the second prints Two, the third prints Three, simultaneously start Three threads, ask to print in the order of One, Two, Three

Subject analysis

Communication between multiple threads. Three threads start randomly, so how do you get them to print sequentially?

We know that there are only two kinds of relationships between threads: competition and collaboration

  • Contention: Each thread competes for printing to determine whether the current state is its turn to print.
  • Synergy: When the current thread prints, the next waiting thread is notified.

Code implementation

Let’s start with a competitive implementation. Three threads will preempt the lock after starting, and the thread that obtains the lock will judge whether the condition of printing is met. If not, the lock will be released, and the three threads will preempt the lock again.

The realization of the judgment condition is as follows: maintain a state, the initial value is 0, and the corresponding values of num of the three thread bindings are 0, 1, 2 respectively. Only when state % 3 == num can the printing condition be met, and the state increases by 1.

Obviously, the disadvantage of multi-threaded competition is that the thread preemption lock is completely scheduled by THE CPU. It may appear that the line that should not be printed is scheduled first and has been preemption lock, but the printed thread has not been scheduled, resulting in CPU performance waste.

Sample code:

public class Test {

    public static final int times = 1;
    public static final int mod = 3;
    public static int state = 0;
    public static final Lock lock = new ReentrantLock();

    static class Task implements Runnable {
        private final int num;
        private final String context;
        public Task(int num, String context) {
            this.num = num;
            this.context = context;
        }

        @Override
        public void run(a) {
            for (int i = 0; i < times;) {
                lock.lock();
                if(state % mod == num) { System.out.println(context); state++; i++; } lock.unlock(); }}}public static void main(String[] args) {
        Task one = new Task( 0."one");
        Task two = new Task(1."two");
        Task three = new Task(2."three");
        new Thread(one).start();
        new Thread(two).start();
        new Thread(three).start();
        while (true) {}}}Copy the code

In the collaborative implementation mode, the current thread notifies the next thread after printing, and the notification mechanism will theoretically have higher execution efficiency.

For communication between multiple threads, we can use wait/notify, or await/signal of Condition.

Sample code:

public class Test {

    public static final Object object = new Object();

    static class Task implements Runnable {
        private boolean flag;
        private final Task preTask;
        private final String context;
        public Task(Task preTask, String context) {
            this.preTask = preTask;
            this.context = context;
        }

        @Override
        public void run(a) {
            synchronized (object) {
                if(preTask ! =null && !preTask.flag) {
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(context);
                flag = true; object.notifyAll(); }}}public static void main(String[] args) {
        Task one = new Task( null."one");
        Task two = new Task(one, "two");
        Task three = new Task(two, "three");
        new Thread(one).start();
        new Thread(two).start();
        new Thread(three).start();
        while (true) {}}}Copy the code