概念: 多线程在并发环境中的正常执行顺序是随机无序的,并不能按照期盼的结果输出。

因为启动一个线程时,线程并不会立即执行,而是等待CPU的资源调度,CPU能调度哪个线程,是通过多种复杂的算法计算而来。

(一)Thread的join()方法来解决这个问题

一般在多线程编程时,需要控制线程的先后执行顺序,比如:主线程中写了子线程t1,想要的效果是需要t1先执行,然后再执行接下来的主线程操作,但是默认的是主线程先执行,所以问题就出现了,执行结果与预期结果不一致。

有两个线程t1和t2,现在让t1比t2先执行:

  1. Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
    Sysout.out.print("t1");
    }
    });
  1. Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
    try {
    // 引入t1线程,等待t1线程的run方法执行完 ,t2才会继续执行
    t1.join();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    Sysout.out.print("t2");
    }
    });
t2.start();
t1.start();
执行结果t1 t2

总结:

多线程编程时,可通过join()方法控制线程的先后执行顺序。 join方法:让主线程等待子线程运行结束后再继续运行

(二) 单一线程池 Excutors.newSingleThreadExecutor()

public class Test {
private static ExecutorService executor = Executors.newSingleThreadExecutor(); public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new MyThread1());
Thread t2 = new Thread(new MyThread2());
Thread t3 = new Thread(new MyThread3());
executor.submit(t1);
executor.submit(t2);
executor.submit(t3);
executor.shutdown();
} }

总结:

利用并发包里的Excutors的newSingleThreadExecutor产生一个单线程的线程池,

而这个线程池的底层原理就是一个先进先出(FIFO)的队列。

代码中executor.submit依次添加了t1 t2 t3线程,按照FIFO的特性,执行顺序也就是t1 t2 t3的执行结果,从而保证了执行顺序。

(三)使用CountDownLatch

final int count = 10; // 计数次数
final CountDownLatch latch = new CountDownLatch(count);//创建CountDownLatch 实例 预定计数次数:10
for (int i = 0; i < count; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
// do anything
System.out.println("线程"
+ Thread.currentThread().getId());
} catch (Throwable e) {
// whatever
} finally {
// 很关键, 无论上面程序是否异常必须执行countDown,否则await无法释放
latch.countDown();//递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
// 如果当前计数大于零,则将计数减少 1
}
}
}).start();
}
try {
// 10个线程countDown()都执行之后才会释放当前线程,程序才能继续往后执行
latch.await();
} catch (InterruptedException e) {
// whatever
}
System.out.println("Finish");
输出:
线程14
线程13
线程15
线程18
线程20
线程17
线程16
线程22
线程21
线程19
Finish

总结:

java.util.concurrent.CountDownLatch

一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

用给定的计数初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。

到达0之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。

最常见的使用场景: 等待其他线程处理完才继续当前线程。

最重要的是使用非常简单!

参考:https://blog.csdn.net/u013407384/article/details/79999022

Java多线程之控制执行顺序的更多相关文章

  1. Java Object 构造方法的执行顺序

    Java Object 构造方法的执行顺序 @author ixenos 为了使用类而做的准备工作包括三个步骤 1)加载:类加载器查找字节码(一般在classpath中找),从字节码创建一个Class ...

  2. 夯实Java基础系列7:一文读懂Java 代码块和执行顺序

    目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...

  3. 夯实Java基础系列7:Java 代码块和执行顺序

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  4. (转)java for循环的执行顺序和几种常用写法

    算是温习吧.问题比较基础,但是也比较重要.(虽然是C,但是很经典) for循环可以说在每个程序中都少不了的,语句头包括三个部分:初始化,判读条件,一个表达式. 但是这三个部分的执行顺序是什么,这是我们 ...

  5. java中静态代码执行顺序

    1.Java中静态变量只能在类主体中定义,不能在方法中定义. 静态变量属于类所有而不属于方法. 2. 静态块:用static申明,JVM加载类时执行,仅执行一次 构造块:类中直接用{}定义,每一次创建 ...

  6. java 方法参数的执行顺序

    java方法的参数的执行顺序是从左到右还是从右到左呢? 写出一下测试程序: 1 import java.util.*; 2 import java.io.*; 3 public class Test ...

  7. [转]多个ajax请求时控制执行顺序或全部执行后的操作

    本文转自:https://blog.csdn.net/fsdad/article/details/71514822 一.当确保执行顺序时: 1. 请求加async: false,,这样所有的ajax就 ...

  8. 多个ajax请求时控制执行顺序或全部执行后的操作

    1.当确保执行顺序时 (1)请求加async: false,,这样所有的ajax就会同步执行,请求顺序就是代码顺序: (2)$.when   确保所有异步的ajax请求完毕时 $.when($.aja ...

  9. Java初始化块及执行顺序

    理解 初始化块又称为代码块.属于类中的第四大成员.本质上是一个方法,它也有方法体,但没有方法名,没有参数,没有返回,而且也不是通过对象或类名显式调用,而是通过隐式调用 是构造器的补充 语法 [修饰符] ...

随机推荐

  1. SpringBoot系列: Redis 共享Session

    Web项目Session管理是一个很重要的话题, 涉及到系统横向扩展, SpringBoot已经为共享Session很好的解决方案, 这篇文章关注使用Redis共享会话, 同时这也是最常用的方法. = ...

  2. impala系列:impala特有的操作符

    --=======================Impala 特有的操作符--=======================ILIKE 操作符, 忽略大小写的 like 操作符.REGEXP 操作符 ...

  3. springboot(二十一):SpringBoot使用Mybatis注解开发教程-分页-动态sql

    https://blog.csdn.net/KingBoyWorld/article/details/78948304

  4. jsp快速开始

    [greeting.jsp] <%@ page contentType="text/html;charset=UTF-8" language="java" ...

  5. 【51nod 1100】斜率最大

    Description 平面上有N个点,任意2个点确定一条直线,求出所有这些直线中,斜率最大的那条直线所通过的两个点.   (点的编号为1-N,如果有多条直线斜率相等,则输出所有结果,按照点的X轴坐标 ...

  6. 利用ssh操控远程服务器

    这里的”远程”操控的方法实际上也不是真正的远程.,這此操作方法主要是在一个局域网内远程操控电脑 (在一个路由器下).可以把它做成在互联网中的远程操控, 不过技术难度上加了一个等级, 如果你想是想人在公 ...

  7. oracle查看表空间数据文件使用情况

    -- 查看表空间数据文件使用情况 select a.*, round(a.usedgb/a.maxgb*100) || '%' usedPer from ( select t.TABLESPACE_N ...

  8. struts2简单入门

    框架是什么,框架有什么作用 框架 实现部分功能的代码. 作用 控制请求和响应. 相对于WEB项目的执行流程 struts2项目搭建流程 配置web.xml 配置前端控制器[核心控制器] ---一个fi ...

  9. linux scanf函数%d后加空白

    参考链接: https://bbs.csdn.net/topics/390389059 关键点: scanf()中空白字符(包括/n,space)会使scanf()函数在读操作中略去输入中的零个或者一 ...

  10. 基于【字节】操作的IO接口:InputStream、OutputStream

    InputStream 参考链接:对java中FileInputStream.BufferInputStream的理解 /** * Author:Mr.X * Date:2017/10/9 17:11 ...