首页 > 编程语言 >java八股复习指南-多线程篇

java八股复习指南-多线程篇

时间:2024-07-17 14:08:59浏览次数:11  
标签:状态 java 复习 Thread 线程 偏向 多线程 方法 轻量级

多线程

线程的实现

在 Java 中,实现多线程的主要有以下四种

  1. 继承 Thread 类,重写 run() 方法;
  2. 实现 Runnable 接口,实现 run() 方法,并将 Runnable 实现类的实例作为 Thread 构造函数的参数 target;
  3. 实现 Callable 接口,实现 call() 方法,然后通过 FutureTask 包装器来创建 Thread 线程;
  4. 通过 ThreadPoolExecutor 创建线程池,并从线程池中获取线程用于执行任务;

不使用Executors创建,而是用ThreadPoolExecutor创建

通过工厂模式,将创建产品实例的权利移交工厂,我们不再通过new来创建我们所需的对象,而是通过工厂来获取我们需要的产品。降低了产品使用者与使用者之间的耦合关系;创建线程池没有显式new,而是通过Executors这个静态方法newCaChedThreadPool来完成的;


Thread类与Runnable接口比较:

实现一个自定义的线程类,可以有继承Thread类或者实现Runnable接口的方式,由于java单继承、多实现的特性,Runnable接口使用比Thread更加灵活

Callable接口:

通常来说,我们使用RunnableThread来创建一个新的线程。但是它们有一个弊端,就是run方法是没有返回值的。而有时候我们希望开启一个线程去执行一个任务,并且这个任务执行完成后有一个返回值

JDK提供了Callable接口与Future类为我们解决这个问题,这也是所谓的“异步”模型。

线程的六种状态:

// Thread.State 源码
public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}
  1. NEW:
  • 不能反复调用同一个线程的start()方法
  • 处于TERMINATED状态的线程不能再次调用start()方法
  1. RUNNABLE:

运行状态。处于RUNNABLE状态的线程在Java虚拟机中运行,也有可能在等待其他系统资源(比如I/O)。

  1. BLOCKED:

阻塞状态。处于BLOCKED状态的线程正等待锁的释放以进入同步区。

  1. WAITING

等待状态。处于等待状态的线程变成RUNNABLE状态需要其他线程唤醒。

以下方法使进程进入等待状态:

  1. TIMED_WAITING

超时等待状态。线程等待一个具体的时间,时间到后会被自动唤醒。

  1. TERMINATED

终止状态。此时线程已执行完毕。

转换成TERMINATED状态的三种方法:

  • Object.wait()
  • Thread.join()
  • LockSupport.park()

Java线程间的通信:

锁与同步

在Java中,锁的概念都是基于对象的,所以我们又经常称它为对象锁。线程和锁的关系,我们可以用婚姻关系来理解。一个锁同一时间只能被一个线程持有。也就是说,一个锁如果和一个线程“结婚”(持有),那其他线程如果需要得到这个锁,就得等这个线程和这个锁“离婚”(释放)。

等待/通知机制

Java多线程的等待/通知机制是基于Object类的wait()方法和notify(), notifyAll()方法来实现的。

信号量

使用volitile关键字实现信号量。volitile关键字能够保证内存的可见性,如果用volitile关键字声明了一个变量,在一个线程里面改变了这个变量的值,那其它线程是立马可见更改后的值的。

其他通信相关

join方法

join()方法是Thread类的一个实例方法。它的作用是让当前线程陷入“等待”状态,等join的这个线程执行完成后,再继续执行当前线程。

sleep方法

sleep方法是Thread类的一个静态方法。它的作用是让当前线程睡眠一段时间。

wait方法与sleep方法的区别:

sleep仅仅释放cpu资源,不会释放锁,所以易死锁。而wait方法会释放cpu资源,也会释放当前锁。

原理篇

volatitle

valatitle 保证内存可见性且禁止重排序

synchronized与锁

四种状态:无锁、偏向锁、轻量级锁、重量级锁

无锁->偏向锁->轻量级锁->重量级锁

  • 偏向锁:

顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。
如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。

  • 轻量级锁:

是指当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。

若当前只有一个等待线程,则该线程通过自旋进行等待。但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁升级为重量级锁。

  • 重量级锁:

在轻量级锁状态下,如果有第三个来访时,就会自动升级成重量级锁

优点 缺点 适用场景
偏向锁 加锁和解锁不需要额外的消耗,和执行非同步方法比仅存在纳秒级的差距。 如果线程间存在锁竞争,会带来额外的锁撤销的消耗。 适用于只有一个线程访问同步块场景。
轻量级锁 竞争的线程不会阻塞,提高了程序的响应速度。 如果始终得不到锁竞争的线程使用自旋会消耗CPU。 追求响应时间。同步块执行速度非常快。
重量级锁 线程竞争不使用自旋,不会消耗CPU。 线程阻塞,响应时间缓慢。 追求吞吐量。同步块执行速度较长。

cas与原子操作

乐观锁与悲观锁

悲观锁:

它总是认为每次访问共享资源时会发生冲突,所以必须对每次数据操作加上锁,以保证临界区的程序同一时间只能有一个线程在执行。

乐观锁:

乐观锁总是假设对共享资源的访问没有冲突,线程可以不停地执行,无需加锁也无需等待。而一旦多个线程发生冲突,乐观锁通常是使用一种称为CAS的技术来保证线程执行的安全性。乐观锁天生免疫死锁

乐观锁多用于“读多写少“的环境,避免频繁加锁影响性能;而悲观锁多用于”写多读少“的环境,避免频繁失败和重试影响性能。

CAS

如果有一个多个线程共享的变量i原本等于5,我现在在线程A中,想把它设置为新的值6;

CAS的全称是:比较并交换(Compare And Swap)。在CAS中,有这样三个值:

  • V:要更新的变量(var),指代变量(i)
  • E:预期值(expected),指旧值(5)
  • N:新值(new),指要设置的值(6)

比较并交换的过程如下:

判断V是否等于E,如果等于,将V的值设置为N;如果不等,说明已经有其它线程更新了V,则当前线程放弃更新,什么都不做。

线程池原理

主要的任务处理流程:

如何做到线程复用

ThreadPoolExecutor在创建线程时,会将线程封装成工作线程worker,并放入工作线程组中,然后这个worker反复从阻塞队列中拿任务去执行。

首先去执行创建这个worker时就有的任务,当执行完这个任务后,worker的生命周期并没有结束,在while循环中,worker会不断地调用getTask方法从阻塞队列中获取任务然后调用task.run()执行任务,从而达到复用线程的目的。只要getTask方法不返回null,此线程就不会退出。

标签:状态,java,复习,Thread,线程,偏向,多线程,方法,轻量级
From: https://www.cnblogs.com/forest-pan/p/18307188

相关文章

  • 使用Java和JHipster快速构建现代化的Web应用
    使用Java和JHipster快速构建现代化的Web应用大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!引言在当今快节奏的软件开发环境中,快速构建现代化的Web应用是开发团队面临的重要挑战之一。本文将介绍如何利用Java和JHipster工具来快速搭建一个现代化的Web应......
  • 华为OD机试D卷 --找座位--24年OD统一考试(Java & JS & Python & C & C++)
    文章目录题目描述输入描述输出描述用例题目解析java源码python源码javascript源码c源码c++源码题目描述在一个大型体育场内举办了一场大型活动,由于疫情防控的需要,要求每位观众的必须间隔至少一个空位才允许落座。现在给出一排观众座位分布图,座位中存......
  • 华为OD机试D卷 --密码输入检测--24年OD统一考试(Java & JS & Python & C & C++)
    文章目录题目描述输入描述输出描述用例题目解析java源码python源码javascript源码c源码c++源码题目描述给定用户密码输入流input,输入流中字符‘<’表示退格,可以清除前一个输入的字符,请你编写程序,输出最终得到的密码字符,并判断密码是否满足如下的密......
  • 如何在Java中实现事件驱动的微服务架构
    如何在Java中实现事件驱动的微服务架构大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!一、引言事件驱动架构(EDA)是一种基于事件进行通信和操作的架构模式,适用于高度分布式和松耦合的系统。微服务架构结合事件驱动可以提升系统的可扩展性和响应性。本文将......
  • Java中的单元测试与集成测试最佳实践
    Java中的单元测试与集成测试最佳实践大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!一、引言在软件开发过程中,测试是保证代码质量和系统稳定性的重要环节。Java作为一种广泛使用的编程语言,其测试工具和框架也非常成熟。本文将详细介绍Java中的单元测试......
  • java八股复习指南
    spring全家桶理解Spring框架核心:ioc和aop1.ioc:控制反转是指把对象的创建和配置的控制权从调用方转移给spring容器,我们可以将对象交给容器管理,即bean,这样不需要自己去new对象,只需要获取bean就可以使用。好比在家自己做菜,菜的味道全部由自己控制;去餐馆吃饭,菜的味道则是交由餐馆......
  • 微信小程序源码-基于Java后端的国产动漫论坛系统毕业设计(附源码+论文)
    大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。......
  • 微信小程序源码-基于Java后端的游戏账号交易系统毕业设计(附源码+论文)
    大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。......
  • 《JavaSE》---12.<面向对象系列之(继承)>
    目录系列文章目录前言一、继承是什么?1.1继承的概念1.2继承的语法1.3父类子类的别名1.4继承的作用1.4继承的代码实践代码示例:输出结果:小结:二、继承中访问成员变量与方法(this与super的用法)2.1当父类成员变量、方法与子类成员变量、方法名字不同时2.2当父类成员变量......
  • JAVA笔记七
    七、数组1.数组的概念(1)一个具有固定大小,可以容纳相同类型数据的集合(2)数组元素的类型可以是基本类型,也可以是引用类型(3)数组可以认为是Java中最简单的复合类型(4)数组的声明和使用,在语法上与C语言类似,但是在内部实现机制上有本质的区别2.数组的声明int[]arr;或者in......