【Java多线程】高级主题:定时调度、quartz、指令重排、volatile、ThreadLocal
定时调度
1000ms后执行 每隔500ms执行一次
package cn.hanquan.test;import java.util.Timer;
import java.util.TimerTask;/** 定时执行*/
public class MyTimer {public static void main(String[] args) {Timer t = new Timer();t.schedule(new MyTask(), 1000, 500);// 1000ms后执行 每隔500ms执行一次}
}class MyTask extends TimerTask {@Overridepublic void run() {System.out.println("大脑放松一下,打印一个hello");}
}
进阶:使用Quartz
官方文档给了很多examples,想实现什么功能,可以直接复制examples里的代码,加以修改。
指令重排
指令重排对多线程是有影响的
sxt Java 300级说这个代码会发生指令重排,但是我测试没有发生重排…
package cn.hanquan.test;import java.util.Timer;
import java.util.TimerTask;/** 指令重排*/
public class HappenBefore {public static int a = 0;public static boolean flag = false;public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 5000; i++) {Thread t1 = new Thread(() -> {a = 1;flag = true;});Thread t2 = new Thread(() -> {if (flag) {a *= 1;// a不变}if (a == 0) {System.out.println("a=" + a);}});t1.start();t2.start();t1.join();t2.join();}}
}
volatile
- volatile用来保证数据的同步,也就是可见性
使用volatile可以让工作内存实时保证最新,保证了同步的数据可见。有一种说法:volatile是轻量级的synchronized,比synchronized占用的资源少,同时也可以避免指令重排
未使用 Volatile
运行之后一直不结束,cpu没有时间同步内存中的值
package cn.hanquan.test;/** 指令重排*/
public class VolatileTest {public static int num = 0;public static void main(String[] args) throws InterruptedException {new Thread(() -> {while (num == 0) {}}).start();Thread.sleep(500);num = 1;}
}
使用 Volatile
程序可以正常结束
package cn.hanquan.test;/** 指令重排*/
public class VolatileTest {public volatile static int num = 0;public static void main(String[] args) throws InterruptedException {new Thread(() -> {while (num == 0) {}}).start();Thread.sleep(500);num = 1;}
}
ThreadLocal
ThreadLocal每个线程有自己的存储区域。自身的数据被修改时,不会影响其他的线程
代码
例1
package cn.hanquan.test;/** 每个线程有自己的存储区域。自身的数据被修改时,不会影响其他的线程*/
public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 5);public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(-100);System.out.println(Thread.currentThread().getName() + "后来->" + threadLocal.get());new Thread(() -> {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(2);System.out.println(Thread.currentThread().getName() + "后来->" + threadLocal.get());}).start();}
}
main初始->5
main后来->-100
Thread-0初始->5
Thread-0后来->2
例2
需要注意threadLocal.get()
的上下文,确定其代表的是哪一个线程
package cn.hanquan.test;/** 每个线程有自己的存储区域。自身的数据被修改时,不会影响其他的线程*/
public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 5);public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(-100);System.out.println(Thread.currentThread().getName() + "后来->" + threadLocal.get());for (int i = 0; i < 5; i++) {new Thread(new myRun()).start();}}public static class myRun implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "初始为->" + threadLocal.get());threadLocal.set(threadLocal.get() - 2);System.out.println(Thread.currentThread().getName() + "后来->" + threadLocal.get());}}
}
main初始->5
main后来->-100
Thread-0初始为->5
Thread-1初始为->5
Thread-0后来->3
Thread-2初始为->5
Thread-1后来->3
Thread-2后来->3
Thread-3初始为->5
Thread-3后来->3
Thread-4初始为->5
Thread-4后来->3
我的理解是:每一个Thread线程都有一个自己的独立threadLocal,可以更改其中的数据的时候,保证其他线程的threadLocal数据不会被修改。但是这有什么意义吗…不知道哪里能用得到?
InheritableThreadLocal
- 可以继承的ThreadLocal
InheritableThreadLocal继承上下文环境的数据,复制一份给子线程(而非共享),相当于线程自己的局部变量
(1)不继承代码示例
package cn.hanquan.test;/** 不继承*/
public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 5);public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(-100);System.out.println(Thread.currentThread().getName() + "后来->" + threadLocal.get());new Thread(() -> {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());}).start();}
}
(2)继承代码示例
package cn.hanquan.test;/** InheritableThreadLocal继承上下文环境的数据,复制一份给子线程*/
public class ThreadLocalTest {private static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>();public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());threadLocal.set(20);System.out.println(Thread.currentThread().getName() + "后来->" + threadLocal.get());new Thread(() -> {System.out.println(Thread.currentThread().getName() + "初始->" + threadLocal.get());}).start();}
}
main初始->null
main后来->20
Thread-0初始->20
CAS
CAS是乐观锁的一种实现:比较并交换
先和原来的值比较。如果原来的值没动过,则交换。如果原来的值被改动过,交换失败。返回false。
效率高,是硬件级别的操作。也可以做到数据的共享。
Atomic原子性的操作都是使用可CAS的思想。
示例代码
【Java多线程】高级主题:定时调度、quartz、指令重排、volatile、ThreadLocal相关推荐
- java多线程高级:JUC
文章目录 java多线程高级:JUC 1 多线程锁 1.1 传统synchronized 1.2 Lock接口 1.3 Synchronized和Lock的区别 2生产者和消费者问题 2.1 Sync ...
- Java并发编程(五)JVM指令重排
我是不是学了一门假的java...... 引言:在Java中看似顺序的代码在JVM中,可能会出现编译器或者CPU对这些操作指令进行了重新排序:在特定情况下,指令重排将会给我们的程序带来不确定的结果.. ...
- [19/04/12-星期五] 多线程_任务定时调度(Timer、Timetask和QUARTZ)
一.Timer和Timetask 通过Timer和Timetask,我们可以实现定时启动某个线程. java.util.Timer 在这种实现方式中,Timer类作用是类似闹钟的功能,也就是定时或者每 ...
- JVM从入门到精通(三):热加载的实现原理,Java内存模型,缓存行,指令重排,合并写技术等
上节回顾:类加载机制 双亲委派机制 parent只是一个成员变量,不是继承关系. 上节课的遗留问题 parent是怎么指定的? 手动指定parent: 双亲委派机制可以被打破吗? 双亲委派机制是在Cl ...
- Java多线程常见面试题及答案汇总1000道(春招+秋招+社招)
Java多线程面试题以及答案整理[最新版]Java多线程高级面试题大全(2021版),发现网上很多Java多线程面试题都没有答案,所以花了很长时间搜集,本套Java多线程面试题大全,汇总了大量经典的J ...
- Java多线程发展简史
摘自: http://www.raychase.net/698 这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从 ...
- [转] Java多线程发展简史
这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从第一个版本开始,在多线程编程方面的大事件和发展脉络有一个描述,并 ...
- Java多线程_1_Java内存模型_内存模型的3大特性
Java内存模型: 内存分布情况及其关系: 主内存:Java内存模型规定所有的变量都保存在主内存中 工作内存:每个线程都有自己的工作内存,保存了该线程使用到的变量的主内存副本拷贝 主内存与工作内存的关 ...
- Java 多线程发展简史
历史热门文章: 可以和面试官聊半个小时的volatile原理 Java中七个潜在的内存泄露风险,你知道几个? JDK 16新特性一览 啥?用了并行流还更慢了 InnoDB自增原理都搞不清楚,还怎么CR ...
最新文章
- lzma打包exe_Web 项目打包EXE
- C# 读写excel 用于导入数据库 批量导入导出excel
- Django在settings.py设置安装软件路径,遇到 'Settings' object is not subscriptable报错
- python解释器用什么写的_用 Python 从零开始写一个简单的解释器(3)
- 白板机器学习笔记 P22-P27 PCA降维
- 结合源码探讨Android距离传感器亮灭屏机制
- 一些牛人博客,值得收藏和学习
- 微正指纹识别算法MZFinger5.0
- 使用realsense t265测试svo2.0视觉里程计
- 「京东白条」的数据架构进化之路!
- ARM嵌入式核心板介绍
- Kotlin GreenDao
- 在云端管理您的所有身份(AAD)-第一部分
- 手把手带你撸一个校园APP(五):新闻中心模块
- Druid监控页面配置reset-enable的说明
- 记录一次京东面试吧,面试的是虚拟平台的经验.
- 2012回家过年:西安火车站遭遇碰瓷
- js单行代码------对象
- 少年,我看你骨骼惊奇,必是练武奇才,将来维护宇宙正义
- 图片分类-python