zoukankan      html  css  js  c++  java
  • 三个线程T1,T2,T3.保证顺序执行的三种方法

    经常看见面试题:有三个线程T1,T2,T3,有什么方法可以确保它们按顺序执行。今天手写测试了一下,下面贴出目前想到的3种实现方式

    说明:这里在线程中我都用到了sleep方法,目的是更容易发现问题。之前看到其他人写的错误代码,测试了好多遍没测试出问题,比如下面这种错误方式

    错误方式(最开始测试,一直都是正确的输出顺序,放开了sleep 注释部分,输出顺序直接不是  t3,t2,t1。错误显而易见)

            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();

    下面说明一下正确的实现方式

    第一种方式:顺序在线程中创建实例(最容易想到的办法)。

    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线程执行

                  //T1线程执行

            }
            
    }

    第二种方式:看到有人说运用单个线程池(SingleThreadExecutor)来实现,确切的说这里不太符合,从打印结果看出,其实我们是在一个线程里,执行了三个任务。

                 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();
    //        }
    

      以上就是 三个线程的顺序实现方式介绍,看了其他的博客潦草写的实现,不假思索的错误实现,希望各位自己在写东西的时候多加思考和论证!以上若有错误,欢迎评论指正

  • 相关阅读:
    SDOI 2009 HH的项链
    SDOI2012 longge的问题
    SDOI 2010 星际竞速
    SDOI2009 晨跑
    SDOI2008 仪仗队
    让我们来看一看C++ 三.表达式与运算符
    如何判断素数
    让我们来看一看C++ 一.对世界说你好
    币种校验的安全问题随笔
    Nodejs代码安全审计之YAPI
  • 原文地址:https://www.cnblogs.com/liran123/p/9313830.html
Copyright © 2011-2022 走看看