JUC-8.共享模型之工具
8.共享模型之工具Future主要方法 核心思想:当你提交一个任务(如到 ExecutorService 线程池)时,它不会立即返回结果,而是立即返回一个 Future 对象。你可以通过这个 Future 对象在未来的某个时间点获取任务执行的结果。 Future<V> 接口定义了以下关键方法: boolean cancel(boolean mayInterruptIfRunning) 作用:尝试取消与此 Future 关联的任务的执行。 参数:mayInterruptIfRunning 为 true 表示如果任务正在运行,则中断执行任务的线程;为 false 则允许正在运行的任务完成。 返回值:如果任务无法被取消(通常是因为它已经正常完成),则返回 false;否则返回 true。 boolean isCancelled() 作用:如果此任务在正常完成之前被取消,则返回 true。 boolean isDone() 作用:如果此任务已完成,则返回 true。完成的原因可能是正常终止、异常或取消——在所有这些情况下,此方法都将返回 true。 V g...
JUC-7.共享模型之不可变
7.共享模型之不可变 不可变类的使用 不可变类设计 无状态类设计 7.1 日期转换的问题问题提出下面的代码在运行时,由于 SimpleDateFormat 不是线程安全的 12345678910SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");for (int i = 0; i < 10; i++) { new Thread(() -> { try { log.debug("{}", sdf.parse("1951-04-21")); } catch (Exception e) { log.error("{}", e); } }).start();} 有很大几率出现 java.lang.NumberForm...
JUC-6.共享模型之无锁
6.共享模型之无锁6.1 问题提出 (应用之互斥)有如下需求,保证 account.withdraw 取款方法的线程安全 123456789101112131415161718192021222324252627282930313233package cn.itcast;import java.util.ArrayList;import java.util.List;interface Account { // 获取余额 Integer getBalance(); // 取款 void withdraw(Integer amount); /** * 方法内会启动 1000 个线程,每个线程做 -10 元 的操作 * 如果初始余额为 10000 那么正确的结果应当是 0 */ static void demo(Account account) { List<Thread> ts = new ArrayList<>(); long start = System.nanoTime...
JUC-5.共享模型之内存
5.共享模型之内存本章内容上一章讲解的Monitor 主要关注的是访问共享变量时,保证临界区代码的原子性这一章我们进一步深入学习共享变量在多线程间的【可见性】问题与多条指令执行时的【有序性】问题 5.1 Java 内存模型JMM 即 Java Memory Model,它定义了主存、工作内存抽象概念,底层对应着 CPU 寄存器、缓存、硬件内存、 CPU 指令优化等。 JMM的意义 计算机硬件底层的内存结构过于复杂,JMM的意义在于避免程序员直接管理计算机底层内存,用一些关键字synchronized、volatile等可以方便的管理内存。 JMM 体现在以下几个方面 原子性 - 保证指令不会受到线程上下文切换的影响 可见性 - 保证指令不会受 cpu 缓存的影响 有序性 - 保证指令不会受 cpu 指令并行优化的影响 5.2 可见性退不出的循环先来看一个现象,main 线程对 run 变量的修改对于 t 线程不可见,导致了 t 线程无法停止: 1234567891011static boolean run = true;public static void mai...
JUC-4.共享模型之管程
4.共享模型之管程本章内容 共享问题 synchronized 线程安全分析 Monitor wait/notify 线程状态转换 活跃性 Lock 4.1共享带来的问题Java代码示例两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗? 123456789101112131415161718static int counter = 0;public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; i < 5000; i++) { counter++; } }, "t1"); Thread t2 = new Thread(() -> { for (int i = 0; ...
JUC-3.Java 线程
3.Java 线程本章内容 创建和运行线程 查看线程 线程 API 线程状态 3.1 创建和运行线程方法一,直接使用 Thread12345678// 创建线程对象 (匿名内部类)Thread t = new Thread() { public void run() { // 要执行的任务 }};// 启动线程t.start(); 例如: 123456789// 构造方法的参数是给线程指定名字,推荐Thread t1 = new Thread("t1") { @Override // run 方法内实现了要执行的任务 public void run() { log.debug("hello"); }};t1.start(); 输出: 119:19:00 [t1] c.ThreadStarter - hello 方法二,使用 Runnable 配合 Thread把【线程】和【任务】(要执...
JUC-2.进程与线程
1. 概览大纲 预备知识 希望你不是一个初学者 线程安全问题,需要你接触过 Java Web 开发、Jdbc 开发、Web 服务器、分布式框架时才会遇到 基于 JDK 8,最好对函数式编程、lambda 有一定了解 采用了 slf4j 打印日志,这是好的实践 采用了 lombok 简化 java bean 编写 给每个线程好名字,这也是一项好的实践 2.进程与线程本章内容 进程和线程的概念 并行和并发的概念 线程基本应用 2.1 进程与线程进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在 指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的 。 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。 进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器 等),也有的程序只能启动一个实例进程(例如网易云音乐、360 安全卫士等) 线程 一个进程之内可以分为一到多个线程。 一个线程就是一个指令流,将指令流中的一条条...
JVM-4.内存模型
内存模型1. java 内存模型很多人将【java 内存结构】与【java 内存模型】傻傻分不清,【java 内存模型】是 Java Memory Model(JMM)的意思。 简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据的可见性、有序 性、和原子性的规则和保障 1.1 原子性原子性在学习线程时讲过,下面来个例子简单回顾一下:问题提出,两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗? 1.2 问题分析以上的结果可能是正数、负数、零。为什么呢?因为 Java 中对静态变量的自增,自减并不是原子操 作。 例如对于 i++ 而言(i 为静态变量),实际会产生如下的 JVM 字节码指令: 1234getstatic i // 获取静态变量i的值 iconst_1 // 准备常量1 iadd // 加法 putstatic i // 将修改后的值存入静态变量 而对应 i– 也是类似: 1234getstatic i // 获取静态变量i的值 iconst_1 // 准备常量1 isub // 减法 pu...
JVM-3.类加载与字节码技术
三、类加载与字节码技术 类文件结构 字节码指令 编译期处理 类加载阶段 类加载器 运行期优化 1、类文件结构一个简单的 HelloWorld.java 123456// HelloWorld 示例 public class HelloWorld { public static void main(String[] args) { System.out.println("hello world"); } } 执行 javac -parameters -d .HelloWorld.java 12javac是编译 -d是打包 .是代表当前目录 HelloWorld.java是要编译的java程序你在cmd下你输入的命令肯定是有目录的.比如前面是C:\>那么你所输入的命令就代表在c盘根目录下进行操作.如果你想要把生成的.class文件放在其他位置比如d盘根目录,那么命令就变为javac -d d:\ HelloWorld.java 编译为 HelloWorld.class 后是这样的 根据 JVM...
JVM-2.垃圾回收
二、垃圾回收1. 如何判断对象可以回收1.1引用计数法 有引用+1 断开引用-1 弊端:循环依赖问题 java未使用该方法 1.2 可达性分析计算法 Java 虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象 扫描堆中的对象,看是否能够沿着 GC Root对象 为起点的引用链找到该对象,找不到,表示可以 回收 哪些对象可以作为 GC Root ? 类比葡萄串🍇,提起葡萄还在根上的就不能被回收案例: 保存jmap状态 1234567891011❯ jps31112 Main34184 Jps33769 Launcher33770 Demo2_2❯ jmap -dump:format=b,live,file=1.bin 33770Dumping heap to /Users/cyt/workspace/java/jvm-std/jvm/src/cn/itcast/jvm/t2/1.bin ...Heap dump file created❯ jmap -dump:format=b,live,file=2.bin 33770Dumping heap to /U...









