3つのスレッドT 1,T 2,T 3.保証順序実行の3つの方法

19328 ワード

3つのスレッドT 1,T 2,T 3があり、どのような方法で順番に実行できるかをよく見ます。今日は手書きで試してみましたが、今まで考えていた3つの実現方法を以下に示します。


説明:ここではスレッドでsleepメソッドを使用しています。問題を発見しやすくすることを目的としています。前に他の人が書いたエラーコードを見て、何度もテストしても問題が発生しませんでした。例えば、次のようなエラー方法です。


エラーモード(最初のテストは、常に正しい出力順序であり、sleepコメント部分を放して、出力順序は直接t 3,t 2,t 1ではありません。エラーは明らかです)

        public static void main(String[] args) {

            final Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
//                    try {
//                        Thread.sleep(100);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                    System.out.println("t1");
                }
            });
            final Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                       // Thread.sleep(50);
                        // t1 , t1 
                        t1.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t2");
                }
            },"t2");
           final Thread t3 = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                       // Thread.sleep(10);
                        // t2 , t2 
                        t2.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t3");
                }
            });
            t1.start();
            t2.start();
            t3.start();

 

正しい実現方法について説明します


1つ目の方法:スレッドにインスタンスを順番に作成します(最も考えやすい方法).
public class TestTwo {
        static TestTwo t=new TestTwo();
        class T1 extends Thread{
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //T1 
                System.out.println("T1 ")
            }
        }

        class T2 extends Thread{
            @Override
            public void run() {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //T2 
                System.out.println("T2 ");
                t.new T1().start();
            }
        }

        class T3 extends Thread{
            @Override
            public void run() {
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //T3 
                System.out.println("T3 ");
                t.new T2().start();
            }
        }
        
        public static void main(String[] args) {
            t.new T3().start();
       // :
             //T3
        //T2

///T 1スレッド実行
        }
        
}

2つ目の方法は、単一のスレッドプール(SingleThreadExecutor)を使用して実装されているという人がいるのを見て、正確にはここはあまり一致していません.印刷結果から見ると、実は私たちは1つのスレッドの中で、3つのタスクを実行しています.
             Thread t1 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " run 1");
}
}, "T1");
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " run 2");
}
}, "T2");
Thread t3 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " run 3");
}
}, "T3");

// ,
ExecutorService executor = Executors.newSingleThreadExecutor();

executor.submit(t3);
executor.submit(t2);
executor.submit(t1);
executor.shutdown();
// :
// pool-1-thread-1 run 3
// pool-1-thread-1 run 2
// pool-1-thread-1 run 1

第三の方式:スレッドのjoin方法を用いて実現する
joinメソッド実装原理とパラメータ説明このブログを参照すると、余分なCP作業は不要です.https://www.cnblogs.com/lcplcpjava/p/6896904.html
public class Testt {

    static Testt t=new Testt();

    class T1 extends Thread{
        public T1(String name){
            super(name);
        }
        @Override
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //T3 
            System.out.println("T1 ");
            for(int i=0;i<10;i++){
                System.out.println(this.getName() + ":" + i);
            }
        }
    }

    class T2 extends Thread{
        public T2(String name){
            super(name);
        }
        @Override
        public void run() {
            //T3 
            System.out.println("T2 ");
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for(int i=0;i<10;i++){
                System.out.println(this.getName() + ":" + i);
            }
        }
    }

    class T3 extends Thread{
        public T3(String name){
            super(name);
        }
        @Override
        public void run() {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //T3 
            System.out.println("T3 ");
            for(int i=0;i<10;i++){
                System.out.println(this.getName() + ":" + i);
            }
        }
    }

    public static void main(String[] args) {
        try {
           T3 t3= t.new T3("T3");
            t3.start();// t3 
            t3.join();// , t3 

            T2 t2= t.new T2("T2");
            t2.start();// t3 
            t2.join();// , t3 

            T1 t1= t.new T1("T1");
            t1.start();// t3 
            t1.join();// , t3 

//            T3 
//            T3:0
//            T3:1
//            T3:2
//            T3:3
//            T3:4
//            T3:5
//            T3:6
//            T3:7
//            T3:8
//            T3:9
//            T2 
//            T2:0
//            T2:1
//            T2:2
//            T2:3
//            T2:4
//            T2:5
//            T2:6
//            T2:7
//            T2:8
//            T2:9
//            T1 
//            T1:0
//            T1:1
//            T1:2
//            T1:3
//            T1:4
//            T1:5
//            T1:6
//            T1:7
//            T1:8
//            T1:9
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}

参考ブログ:https://blog.csdn.net/yuwinter/article/details/78772933
ここのブログの書き方には間違いがあることに注意してください.ここのjoin方法は同じインスタンスに対して、そうでなければ役に立たないです.具体的には、上のリンクを参照してjoin実装原理を参照してください.
//        try {
//            t.new T3().start();// t3 
//            t.new T3().join();// , t3 
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        try {
//            t.new T1().start();// t1 
//            t.new T1().join();// , t1 
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        try {
//            t.new T2().start();// t2 
//            t.new T2().join();// , t2 
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

以上、三つのスレッドの順番の実現方法を紹介しましたが、他のブログの乱筆の実現を見て、考えずに誤った実現を実現しました.以上、間違いがあれば、コメントを歓迎します.