java保证多线程的执行顺序
1. java多线程环境中,如何保证多个线程按指定的顺序执行呢?
1.1 通过thread的join方法保证多线程的顺序执行, wait是让主线程等待
比如一个main方法里面先后运行thread1,,thread2,thread3,那么thread1.start()之后,运行thread1.join(),这是会让主线程mian等待新的线程thread1执行完了,再执行主线程mian下面的代码,thread1.join()是然主线程main wait。
package com.java.yj;
/**
* Created by yejian on 2018/7/9.
*/
public class MultiThread {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Thread1());
thread1.start();
thread1.join();
Thread thread2 = new Thread(new Thread2());
thread2.start();
thread2.join();
Thread thread3 = new Thread(new Thread3());
thread3.start();
}
public static class Thread1 implements Runnable{
@Override
public void run() {
System.out.println("Thread1");
}
}
public static class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("Thread2");
}
}
public static class Thread3 implements Runnable{
@Override
public void run() {
System.out.println("Thread3");
}
}
}
1.2 ExecutorService executor = Executors.newSingleThreadExecutor()
java5以后提供的一个多线程操作方法,创建一个只有一个线程的线程池操作,会创建一个线程队列,按FIFO的顺序执行里面的线程。
package com.java.yj;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by yejian on 2018/7/9.
*/
public class MultiThread2 {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Thread1());
executor.submit(new Thread2());
executor.submit(new Thread3());
executor.shutdown();
}
public static class Thread1 implements Runnable{
@Override
public void run() {
System.out.println("Thread1");
}
}
public static class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("Thread2");
}
}
public static class Thread3 implements Runnable{
@Override
public void run() {
System.out.println("Thread3");
}
}
}
2. java中的volatile和synthronized
2.1JMM-java memory model
解决并发过程中如何处理可见性,原子性,有序性的问题
runnable ,thread。
并发编程中的2个关键问题:
a. 线程间如何通信 --wait() notify() notifyAll()
a) 共享内存 -隐式通信
b) 消息传递 - 显示通信
b. 线程之间如何同步
在共享内存的并发模型中,同步是显示做的; synchronized
在消息传递的并发模型中,由于小时发送必须在消息接受之前,所以同步是隐式的
2.2. 定位内存可见性问题
什么对象是内存共享的 ,什么不是,堆内存的对象,java虚拟机栈
JMM定义了线程和主内存之间的一个关系。线程之间通讯,必须通过主内存通讯。
volatile、synchronized
volatile 功能,声明了volatile的变量,进行写操作的时候,jvm会向处理器发送一条Lock的前缀指令,会把这个变量所在缓存行的数据写回到系统内存。
在多处理器的情况下,保证各个处理器缓存一致性的特点,会实现缓存一致性协议。改变了值的volatile变量,在其他行程被指为失效状态其他线程要使用这个变量,需要重新到驻村里面去取。
synchronized:可重入锁、互斥性、可见性
volatile 可以做到原子性,可见性,不能做到复合操作的原子性
比如: volatile int i;
i++ 读取i的值,给i加1,把新的值赋值给i,这个i++操作在多线程环境下是无法保证原子性的
synchronized后面锁定的对象,可以是一个类对象,也可以是一个成员变量。
第一个线程进来调用monitorener 和monitorexit实现,获取对象的监视器,释放对象监视器
后续进程过来,如果monitor还没有释放,那么他获取不到这个对象的monitor,会放到一个对列里面:synthronizedQueue。 等到对象的锁释放了,通知synthronizedQueue出队列,获取那个monitor。
3. Lock和synchronized
Lock是java5以后出现的,在juc包: java.util.concurrentlocks
3.1 synthronized的锁什么时候释放
1.1 获取锁的线程执行完了该代码块
1.2 线程出现异常
3.2 synchronized的缺陷
2.1 读写冲突
3.3 Lock可以主动去释放锁,而synchronized是被动的
ReadWriteLock
ReadLock
WriteLock
ReenterantLock可重入锁
可中断锁
公平锁 等待一个锁的实际越长,获取这个锁的几率越高
ReenterantReadWriteLock 可重入读写锁
Lock是java里面的一个接口,有丰富的实现,而synchronized是java的一个关键字,是一个内置的功能
竞争资源激烈的情况,Lock性能优于synchronized,但是jdk7,8对synchronized做了很多优化,性能差异不大。
java保证多线程的执行顺序的更多相关文章
- Java使用多线程异步执行批量更新操作
import com.google.common.collect.Lists; import org.apache.commons.collections.CollectionUtils; impor ...
- Java Object 构造方法的执行顺序
Java Object 构造方法的执行顺序 @author ixenos 为了使用类而做的准备工作包括三个步骤 1)加载:类加载器查找字节码(一般在classpath中找),从字节码创建一个Class ...
- (转)java for循环的执行顺序和几种常用写法
算是温习吧.问题比较基础,但是也比较重要.(虽然是C,但是很经典) for循环可以说在每个程序中都少不了的,语句头包括三个部分:初始化,判读条件,一个表达式. 但是这三个部分的执行顺序是什么,这是我们 ...
- 夯实Java基础系列7:一文读懂Java 代码块和执行顺序
目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...
- 夯实Java基础系列7:Java 代码块和执行顺序
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- java中静态代码执行顺序
1.Java中静态变量只能在类主体中定义,不能在方法中定义. 静态变量属于类所有而不属于方法. 2. 静态块:用static申明,JVM加载类时执行,仅执行一次 构造块:类中直接用{}定义,每一次创建 ...
- java 方法参数的执行顺序
java方法的参数的执行顺序是从左到右还是从右到左呢? 写出一下测试程序: 1 import java.util.*; 2 import java.io.*; 3 public class Test ...
- Java初始化块及执行顺序
理解 初始化块又称为代码块.属于类中的第四大成员.本质上是一个方法,它也有方法体,但没有方法名,没有参数,没有返回,而且也不是通过对象或类名显式调用,而是通过隐式调用 是构造器的补充 语法 [修饰符] ...
- Java Web项目启动执行顺序
一. 1.启动一个WEB项目,WEB容器会先去读取它的配置文件web.xml,读取<context-param>和<listener>两个节点. 2.接着,容器创建一个Serv ...
随机推荐
- layui时间控件闪退的问题
项目上线,发现后台管理系统layui的子页面出现时间控件闪退的问题,根本选取不到时间. 其原因是:如果出现页面找到多个节点,只有第一个节点能正常使用后面的节点都会闪退,可以理解为目前laydate不支 ...
- linux非root用户安装jdk1.8
如题,先到 Oracle 官方网站 下载1.8版本的 JDK 压缩包(jdk-8u221-linux-x64.tar.gz)到本地(如D盘的soft目录),然后开始进入linux的非root用户(如w ...
- Spring cloud微服务安全实战-5-4请求转发及退出
步骤1234已经完成 下面处理 5678这几步.zuul在转发的时候 把请求头加上 获取订单信息 加一个按钮,登陆成功后,去拿订单的信息. 展示获取到的订单信息 ts代码 ts内定义order对象 定 ...
- Spring Boot系列之-helloword入门
一. What: Spring Boot是什么?以1.4.3.RELEASE为例,官方介绍为:http://docs.spring.io/spring-boot/docs/1.4.3.RELEASE/ ...
- 【缺少kubernetes权限】 namespaces "xxx" is forbidden: User "xxx" cannot xxx resource "xxx" in API group "xxx" in the namespace "xxx"
需要添加权限,添加权限方式: https://github.com/argoproj/argo/issues/1068
- JS正则匹配邮箱格式
观察一些邮箱格式,有些邮箱格式简单,有些复杂,在网上找了个邮箱的正则表达式,分析一下邮箱的规则.该表达式:/^\w+([\.\-]\w+)*\@\w+([\.\-]\w+)*\.\w+$/ 拆分:[1 ...
- 【嵌入式硬件Esp32】ESP32 正确下载姿势
程序的正确下载步骤,以8M flash为例子: 一.硬件连接 ESP32 的运行状态主要由 GPIO0 决定 二.ESP32 Flash 地址配置 ESP32 在编译时,通过 make menucon ...
- pod 常用指令
//只安装新增的库,已经安装的库不更新 pod install --verbose --no-repo-update //只更新指定库名的第三个库,其他库不更新 pod update 库名 --ver ...
- 一次性清除页面上的所有setInterval
参考链接:https://www.cnblogs.com/liujinyu/p/3668575.html
- ubuntu18.10 修改MySQL编码为utf-8
首先登陆mysql的交互shell,输入下面的命令查看当前数据库的编码方式 show variables like '%character%'; 从上面可以看出,mysql数据库装上之后初始并不均是u ...