Java多线程之控制执行顺序
概念: 多线程在并发环境中的正常执行顺序是随机无序的,并不能按照期盼的结果输出。
因为启动一个线程时,线程并不会立即执行,而是等待CPU的资源调度,CPU能调度哪个线程,是通过多种复杂的算法计算而来。
(一)Thread的join()方法来解决这个问题
一般在多线程编程时,需要控制线程的先后执行顺序,比如:主线程中写了子线程t1,想要的效果是需要t1先执行,然后再执行接下来的主线程操作,但是默认的是主线程先执行,所以问题就出现了,执行结果与预期结果不一致。
有两个线程t1和t2,现在让t1比t2先执行:
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Sysout.out.print("t1");
}
});
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多线程之控制执行顺序的更多相关文章
- Java Object 构造方法的执行顺序
Java Object 构造方法的执行顺序 @author ixenos 为了使用类而做的准备工作包括三个步骤 1)加载:类加载器查找字节码(一般在classpath中找),从字节码创建一个Class ...
- 夯实Java基础系列7:一文读懂Java 代码块和执行顺序
目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...
- 夯实Java基础系列7:Java 代码块和执行顺序
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- (转)java for循环的执行顺序和几种常用写法
算是温习吧.问题比较基础,但是也比较重要.(虽然是C,但是很经典) for循环可以说在每个程序中都少不了的,语句头包括三个部分:初始化,判读条件,一个表达式. 但是这三个部分的执行顺序是什么,这是我们 ...
- java中静态代码执行顺序
1.Java中静态变量只能在类主体中定义,不能在方法中定义. 静态变量属于类所有而不属于方法. 2. 静态块:用static申明,JVM加载类时执行,仅执行一次 构造块:类中直接用{}定义,每一次创建 ...
- java 方法参数的执行顺序
java方法的参数的执行顺序是从左到右还是从右到左呢? 写出一下测试程序: 1 import java.util.*; 2 import java.io.*; 3 public class Test ...
- [转]多个ajax请求时控制执行顺序或全部执行后的操作
本文转自:https://blog.csdn.net/fsdad/article/details/71514822 一.当确保执行顺序时: 1. 请求加async: false,,这样所有的ajax就 ...
- 多个ajax请求时控制执行顺序或全部执行后的操作
1.当确保执行顺序时 (1)请求加async: false,,这样所有的ajax就会同步执行,请求顺序就是代码顺序: (2)$.when 确保所有异步的ajax请求完毕时 $.when($.aja ...
- Java初始化块及执行顺序
理解 初始化块又称为代码块.属于类中的第四大成员.本质上是一个方法,它也有方法体,但没有方法名,没有参数,没有返回,而且也不是通过对象或类名显式调用,而是通过隐式调用 是构造器的补充 语法 [修饰符] ...
随机推荐
- SQL Server进阶(三)单表查询
示例数据库 点我下载 一条完整的sql语句 select top | distinct 字段, 表达式, 函数, ... from 表表达式 where 筛选条件 group by 分组条件 havi ...
- Slash and BackSlash 记忆法
容易混淆的两兄弟 Slash https://en.wikipedia.org/wiki/Slash Slash (punctuation), the "/" punctuatio ...
- Javaweb——————sql常用思维导图
- ****** 二十八 ******、软设笔记【数据库】-分布式数据库、特点、数据存储、DBMS组成
分布式数据库 一.分布式数据库 分布式数据库由一组数据组成,这些数据物理上分布在计算机网络的不同结点(场地)上,逻辑上是属于同一个系统.每个结点可以执行局部应用,也能通过网络通信子 ...
- 【51nod 1785】数据流中的算法
Description 51nod近日上线了用户满意度检测工具,使用高级人工智能算法,通过用户访问时间.鼠标轨迹等特征计算用户对于网站的满意程度. 现有的统计工具只能统计某一个窗口中,用户的满意程 ...
- table的复制 SqlServer 数据库添加临时表(select 字段1,字段2,字段3 into)
select 字段1,字段2,字段3 into tempname form table where table.id=1; oralce : insert into MID_DRUG_DETA ...
- clam安装
nodejs下,npm安装clam指令: npm install -g clam
- ARM核心板_迅为4418核心板_高稳定超轻薄_研发超灵感
ARM核心板_迅为4418核心板_三星四核S5P4418处理器 4418核心板正面: 4418核心板反面:4418核心板尺寸图:详情了解:https://item.taobao.com/item.ht ...
- vprintf printf区别
参考链接: https://zhidao.baidu.com/question/237458625.html
- Maven 通过maven对项目进行拆分、聚合(重点)
对现在已有maven ssh项目进行拆分,拆分思路:将dao层的代码已经配置文件全体提取出来到一个表现上独立的工程中.同样service.action拆分. ssh-parent: 父工程 ssh-d ...