Resultados de impresión multihilo en orden

Prólogo

El texto ha sido incluido en mi repositorio de GitHub. Bienvenido a Star: github.com/bin39232820 ... El
mejor momento para plantar un árbol fue hace diez años, seguido por ahora.
Sé que muchas personas ya no juegan qq , pero nostalgia, bienvenidos a unirse a seis Pulse Excalibur, grupo de aprendizaje de novatos de Java, número de chat grupal: 549684836, aliente a todos a bloguear en el camino hacia la tecnología

Charla

Este es un problema muy simple de subprocesos múltiples, pero parece muy simple para Primary Six y Six, pero no es tan simple de escribir, lo que indica que el código de Primary Six o Six todavía es demasiado pequeño.

Titulo

Ofrecemos una clase:

public class Foo {
  public void one() { print("one"); }
  public void two() { print("two"); }
  public void three() { print("three"); }
}
复制代码

Tres hilos diferentes compartirán una instancia de Foo.

  • El hilo A llamará a un método ()
  • El hilo B llamará al método two ()
  • El hilo C llamará al método three ()

Diseñe y modifique el programa para asegurarse de que el método two () se ejecute después del método one () y el método three () se ejecute después del método two ().

Ejemplo 1:

输入: [1,2,3]
输出: "onetwothree"
解释: 
有三个线程会被异步启动。
输入 [1,2,3] 表示线程 A 将会调用 one() 方法,线程 B 将会调用 two() 方法,线程 C 将会调用 three() 方法。
正确的输出是 "onetwothree"复制代码

Problema 1: un bloqueo sincronizado y variables de control

package com.code.thread;

/**
 * 上面方法就是采用一个synchronized wait notifyAll  这些来实现的,但是吧,还需要一个while去自旋,还得靠一个信号量,感觉有点low。
 */

class Foo {

    private  int flag=0;
    private Object lock=new Object();
    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {
        synchronized(lock){
            while (flag!=0){
                lock.wait();
            }
            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            flag=1;
            lock.notifyAll();
        }

    }

    public void second(Runnable printSecond) throws InterruptedException {
        synchronized (lock) {
            while (flag != 1) {
                lock.wait();
            }
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            flag = 2;
            lock.notifyAll();
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        synchronized(lock) {
            while (flag != 2) {
                lock.wait();
            }
            // printThird.run() outputs "third". Do not change or remove this line.
            printThird.run();
            lock.notifyAll();
        }
    }

    public static void main(String[] args) throws Exception {
        final Foo foo = new Foo();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.first(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(1);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.second(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(2);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.third(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(3);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t3.start();
        t2.start();
        t1.start();

    }
}

复制代码

El método anterior se implementa con una notificación de espera sincronizada AllAll, pero, necesita un tiempo para girar, pero también se basa en un semáforo, se siente un poco bajo.

El problema 2 usa CountDownLatch para controlar

  • La clase countDownLatch hace que un hilo espere a que otros hilos completen su ejecución antes de ejecutarse.
  • Se realiza mediante un contador.El valor inicial del contador es el número de subprocesos. Cada vez que un hilo termina de ejecutarse, el valor del contador es -1. Cuando el valor del contador es 0, significa que todos los hilos han terminado de ejecutarse, y luego el hilo en espera puede reanudar el trabajo.
package com.code.thread;

import java.util.concurrent.CountDownLatch;

public class Foo1 {
    //定义2个countDownLatch
    private CountDownLatch countDownLatchA=new CountDownLatch(1); //说明只要一个线程调用它就放行 ,它是到0就放行
    private CountDownLatch countDownLatchB=new CountDownLatch(1);
    public Foo1() {

    }

    public void first(Runnable printFirst) throws InterruptedException {
            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();


    }

    public void second(Runnable printSecond) throws InterruptedException {
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();

    }

    public void third(Runnable printThird) throws InterruptedException {
            // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();

    }

    public static void main(String[] args) throws Exception {
        final Foo1 foo = new Foo1();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.first(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(1);
                        }
                    });
                    foo.countDownLatchA.countDown();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.countDownLatchA.await();
                    foo.second(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(2);
                        }
                    });
                    foo.countDownLatchB.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                    try {
                        foo.countDownLatchB.await();
                        foo.third(new Runnable() {
                            @Override
                            public void run() {
                                System.out.println(3);
                            }
                        });
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
        });
        t3.start();
        t2.start();
        t1.start();

    }
}

复制代码

Método tres del semáforo

Ideas para resolver problemas basadas en semáforos

  • ¿Qué es el semáforo?
  • Semáforo es un semáforo de cuenta que debe ser liberado por el hilo que lo adquirió.
package com.code.thread;

import java.util.concurrent.Semaphore;

/**
 *
 * 基于信号量的解题思路
 * Semaphore 是什么?
 * Semaphore 是一个计数信号量,必须由获取它的线程释放。
 *
 * 常用于限制可以访问某些资源的线程数量,例如通过 Semaphore 限流。
 */
public class Foo2 {

    //初始化Semaphore为0的原因:
    // 如果这个Semaphore为零,如果另一线程调用(acquire)这个Semaphore就会产生阻塞,
    // 便可以控制second和third线程的执行
    private Semaphore spa=new Semaphore(0) ;
    private Semaphore spb=new Semaphore(0);




    public Foo2() {

    }

    public void first(Runnable printFirst) throws InterruptedException {

        printFirst.run();
        spa.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        // printSecond.run() outputs "second". Do not change or remove this line.
        spa.acquire();
        printSecond.run();
        spb.release();
    }

    public void third(Runnable printThird) throws InterruptedException {
        // printThird.run() outputs "third". Do not change or remove this line.
        spb.acquire();
        printThird.run();
    }

    public static void main(String[] args) throws Exception {
        final Foo2 foo = new Foo2();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.first(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(1);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.second(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(2);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    foo.third(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(3);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t3.start();
        t2.start();
        t1.start();

    }
}

复制代码

Solución de problemas 4 LockSupport

En el análisis final, el código nativo en inseguro llamado por LockSupport:

  • público nativo vacío unpark (Thread jthread);
  • parque público nativo vacío (booleano es absoluto, mucho tiempo);
  • Dos declaraciones de funciones explican claramente el objeto de la operación: la función de estacionamiento es bloquear el hilo actual, y la función de estacionamiento es despertar otro hilo.
package com.code.thread;

import java.util.concurrent.locks.LockSupport;

/**'
 * 归根结底,LockSupport调用的Unsafe中的native代码:
 * public native void unpark(Thread jthread);
 * public native void park(boolean isAbsolute, long time);
 * 两个函数声明清楚地说明了操作对象:park函数是将当前Thread阻塞,而unpark函数则是将另一个Thread唤醒。
 *
 * 与Object类的wait/notify机制相比,park/unpark有两个优点:1. 以thread为操作对象更符合阻塞线程的直观定义;2. 操作更精准,可以准确地唤醒某一个线程(notify随机唤醒一个线程,notifyAll唤醒所有等待的线程),增加了灵活性。
 */
public class Foo3 {
    static Thread t1=null,t2=null,t3=null;

    public Foo3() {

    }

    public void first(Runnable printFirst) throws InterruptedException {

        printFirst.run();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
    }

    public void third(Runnable printThird) throws InterruptedException {
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }


        public static void main(String[] args) throws Exception {
            final Foo3 foo = new Foo3();

             t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        foo.first(new Runnable() {
                            @Override
                            public void run() {
                                System.out.println(1);
                            }
                        });
                        LockSupport.unpark(t2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
             t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    LockSupport.park();
                    try {
                        foo.second(new Runnable() {
                            @Override
                            public void run() {
                                System.out.println(2);
                            }
                        });
                        LockSupport.unpark(t3);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
             t3 = new Thread(new Runnable() {
                @Override
                public void run() {
                    LockSupport.park();
                    try {
                        foo.third(new Runnable() {
                            @Override
                            public void run() {
                                System.out.println(3);
                            }
                        });
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            t3.start();
            t2.start();
            t1.start();

    }
}
复制代码

El final

De hecho, hay muchas soluciones. Si no está familiarizado con los subprocesos múltiples, puede ir a mi blog de Github para familiarizarse primero. Esta pregunta debe considerarse un tipo de pregunta simple.

Alabanza diaria

Muy bien todos, lo anterior es el contenido completo de este artículo, pueden ver a las personas aquí, todos son verdaderos fanáticos .

La creación no es fácil. Su apoyo y reconocimiento es mi mayor motivación para la creación. Nos vemos en el próximo artículo.

Liumai Excalibur | Texto [Original] Si hay algún error en este blog, critique e instruya, ¡gracias!

Supongo que te gusta

Origin juejin.im/post/5e999ff0518825738e2180e0
Recomendado
Clasificación