vlambda博客
学习文章列表

4种方法,实现多线程按着指定顺序执行

做积极的人,而不是积极废人!

每天 14:00 更新文章,每天掉亿点点头发...

源码精品专栏

 




文章介绍4种方法,简单易懂,通过4个demo抛砖引玉。

通过join()方法使当前线程“阻塞”,等待指定线程执行完毕后继续执行。

举例:在线程thread2中,加上一句thread1.join(),其意义在于,当前线程2运行到此行代码时会进入阻塞状态,直到线程thread1执行完毕后,线程thread2才会继续运行,这就保证了线程thread1与线程thread2的运行顺序。

public class ThreadJoinDemo {
  public static void main(String[] args) throws InterruptedException {
    final Thread thread1 = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("打开冰箱!");
      }
    });

    final Thread thread2 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          thread1.join();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("拿出一瓶牛奶!");
      }
    });

    final Thread thread3 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          thread2.join();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("关上冰箱!");
      }
    });

    //下面三行代码顺序可随意调整,程序运行结果不受影响,因为我们在子线程中通过“join()方法”已经指定了运行顺序。
    thread3.start();
    thread2.start();
    thread1.start();

  }
}

运行结果:

打开冰箱!
        拿出一瓶牛奶!
        关上冰箱!

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。

简单说一下子线程与主线程的区别,子线程指的是发生在Thread内部的代码,主线程指的是发生在main函数中的代码,我们可以在main函数中通过join()方法让主线程阻塞等待以达到指定顺序执行的目的。

public class ThreadMainJoinDemo {
  public static void main(String[] args) throws InterruptedException {
    final Thread thread1 = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("打开冰箱!");
      }
    });

    final Thread thread2 = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("拿出一瓶牛奶!");
      }
    });

    final Thread thread3 = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("关上冰箱!");
      }
    });

    thread1.start();
    thread1.join();
    thread2.start();
    thread2.join();
    thread3.start();
  }
}

输出结果:

打开冰箱!
        拿出一瓶牛奶!
        关上冰箱!

基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。

CountDownLatch通过计数器提供了更灵活的控制,只要检测到计数器为0当前线程就可以往下执行而不用管相应的thread是否执行完毕。

public class ThreadCountDownLatchDemo {

  private static CountDownLatch countDownLatch1 = new CountDownLatch(1);

  private static CountDownLatch countDownLatch2 = new CountDownLatch(1);

  public static void main(String[] args) {
    final Thread thread1 = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("打开冰箱!");
        countDownLatch1.countDown();
      }
    });

    final Thread thread2 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          countDownLatch1.await();
          System.out.println("拿出一瓶牛奶!");
          countDownLatch2.countDown();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });

    final Thread thread3 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          countDownLatch2.await();
          System.out.println("关上冰箱!");
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });

    //下面三行代码顺序可随意调整,程序运行结果不受影响
    thread3.start();
    thread1.start();
    thread2.start();
  }
}

输出结果:

打开冰箱!
        拿出一瓶牛奶!
        关上冰箱!

单线程化线程池(newSingleThreadExecutor)的优点,串行执行所有任务。

public class ThreadPoolDemo {

  static ExecutorService executorService = Executors.newSingleThreadExecutor();

  public static void main(String[] args) {
    final Thread thread1 = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("打开冰箱!");
      }
    });

    final Thread thread2 =new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("拿出一瓶牛奶!");
      }
    });

    final Thread thread3 = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("关上冰箱!");
      }
    });
    executorService.submit(thread1);
    executorService.submit(thread2);
    executorService.submit(thread3);
    executorService.shutdown();        //使用完毕记得关闭线程池
  }

}

输出结果:

打开冰箱!
        拿出一瓶牛奶!
        关上冰箱!


已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)