经常看见面试题:有三个线程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();
// }

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

三个线程T1,T2,T3.保证顺序执行的三种方法的更多相关文章

  1. 有三个线程T1 T2 T3,如何保证他们按顺序执行-转载

    T3先执行,在T3的run中,调用t2.join,让t2执行完成后再执行t3 在T2的run中,调用t1.join,让t1执行完成后再让T2执行 public class Test { // 1.现在 ...

  2. 有三个线程T1 T2 T3,如何保证他们按顺序执行

    T3先执行,在T3的run中,调用t2.join,让t2执行完成后再执行t3 在T2的run中,调用t1.join,让t1执行完成后再让T2执行 public class JoinTest {     ...

  3. Java:现有线程T1/T2/T3,如何确保T1执行完成之后执行T2,T3在T2执行完成之后执行。

    要实现多个线程执行完成先后,就要知道如何实现线程之间的等待,java线程等待实现是join.java的jdk中join方法实现如下: public final synchronized void jo ...

  4. Java-JUC(零):Java:现有线程T1/T2/T3,如何确保T1执行完成之后执行T2,T3在T2执行完成之后执行。

    要实现多个线程执行完成先后,就要知道如何实现线程之间的等待,java线程等待实现是join.java的jdk中join方法实现如下: public final synchronized void jo ...

  5. join控制线程的执行循序 T1 -> T2 -> T3

    /** * 控制线程的执行循序 T1 -> T2 -> T3 * join实现 */ public static void join(){ Thread t1 = new Thread(( ...

  6. 现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?

    Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); Thread t3 = new Thread(new T3()) ...

  7. java 多线程,T1 T2 T3 顺序执行

    一.程序设计 1.抽象公共类PublicThread,具有先前线程属性previousThread.父类为Thread 2.在PublicThread的run()方法中判断previousThread ...

  8. JS基础入门篇( 三 )—使用JS获取页面中某个元素的4种方法以及之间的差别( 一 )

    1.使用JS获取页面中某个元素的4种方法 1.通过id名获取元素 document.getElementById("id名"); 2.通过class名获取元素 document.g ...

  9. js中页面加载完成后执行的几种方法及执行顺序

    在js和jquery使用中,经常使用到页面加载完成后执行某一方法.通过整理,大概是五种方式(其中有的只是书写方式不一样). 1:使用jQuery的$(function){}; 2:使用jquery的$ ...

随机推荐

  1. 开机后Android应用自动启动

    一.需求 在应用开发过程中,有客户提出在设备开机后自动启动应用. 二.实现方法 实现方案:安卓系统每次开机的时候都会发送一个广播,监听这个广播,广播事件触发启动应用程序. 监听音频广播而不是启动广播, ...

  2. 前端开发JS白板编程题目若干

    在前端开发参加面试的时候,无论是校招还是社招,往往都会碰到让我们直接在白纸或者白板上手撸代码的题目.由于是手撸代码,这些题目肯定不会过于复杂和冗长,否则面试那么一小会时间根本写不完.本文总结了几个我本 ...

  3. js 大厦之JavaScript事件

    1.js事件简介 事件(Event) 是 JavaScript 应用跳动的心脏 ,进行交互,使网页动起来.也是把所有东西粘在一起的胶水.当我们与浏览器中 Web 页面进行某些类型的交互时,事件就发生了 ...

  4. 电脑知识,一键开启Win10“超级性能模式”

    现在主流系统以及从WIN7慢慢的转移到了WIN10,微软也为WIN10做了很多优化跟更新.今天要跟大家说的这个功能很多人肯定没有听说过.那就是WIN10的超级性能模式. 1. 大多数Win10是没有滴 ...

  5. Go语言数组

    目录 声明数组 数组在内存的结构 初始化数组 使用数组 函数间传递数组 数组使用注意事项 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列(这是一种同构的数据结构);这种类型可以是任意的原始类 ...

  6. Python的简单介绍

    0. 前言 最近在从头梳理Python的相关知识,有助于以后更好地学习新知识.这篇博客,我简单介绍一下Python语言的有关内容. 1. Python介绍 Python的创始人为荷兰人吉多·范罗苏姆( ...

  7. 传参导出Excel表乱码问题解决方法

    业务场景 先描述一下业务场景,要实现的功能是通过搜索框填写参数,然后点击按钮搜索数据,将搜索框的查询参数获取,附加在链接后面,调导Excel表接口,然后实现导出Excel功能.其实做导Excel表功能 ...

  8. 【spring】aop切面通知,日志处理

    1.spring的切面编程 概念原理可以看这里:http://blog.csdn.net/moreevan/article/details/11977115 2.所需要的jar包 maven引入jar ...

  9. Java之单元测试工具(Junit)

    Junit是Java单元测试框架,一般Eclipse里面会集成这个Junit4测试工具 既然是测试工具,虽然开发用得比较多,但作为测试人员也需要具备会Junit测试的思想,况且技多不压身 这里简单介绍 ...

  10. 实现quartz定时器及quartz定时器原理介绍

    今天研究定时器,在网上看了一篇不错的文章,推荐给大家! 实现quartz定时器及quartz定时器原理介绍