“我愿为并发编程花很多时间” —— Java并发编程中的基础知识

大家好,我是方圆,这篇博客儿主要列举一些并发编程的基础知识


1. Java运行时默认开启线程

// 查看当前所有线程
for (Map.Entry<Thread, StackTraceElement[]> threadEntry : Thread.getAllStackTraces().entrySet()) {
    System.out.println(threadEntry.getKey());
}

控制台输出如下,除了main主线程外,还有其他五个线程,下面逐条解释
在这里插入图片描述

  • Monitor Ctrl-Break: 这个是IDEA开启的线程,监控Ctrl-Break中断信号
  • Attach Listener: Attach Listener线程是负责接收到外部的命令,而对该命令进行执行的并且把结果返回给发送者,通常我们会用一些命令去要求jvm给我们一些反馈信息,如:java -version、jmap、jstack等等
  • Signal Dispatcher: 前面我们提到第一个Attach Listener线程的职责是接收外部jvm命令,当命令接收成功后,会交给signal dispather线程去进行分发到各个不同的模块处理命令,并且返回处理结果。signal dispather线程也是在第一次接收外部jvm命令时,进行初始化工作
  • Finalizer:这个线程也是在main线程之后创建的,其在Java中的优先级为8,主要用于在垃圾收集前,调用对象的finalize()方法;关于Finalizer线程的几点:
  1. 只有当开始一轮垃圾收集时,才会开始调用finalize()方法;因此并不是所有对象的finalize()方法都会被执行
  2. 该线程也是daemon线程,不管该线程有没有执行完finalize()方法,JVM都会退出
  3. JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;最后将该Finalizer对象的引用置为null,由垃圾收集器来回收
for (Thread thread : Thread.getAllStackTraces().keySet()) {
    if ("Finalizer".equals(thread.getName())) {
    	// 查看Finalizer线程的优先级
        System.out.println("Priority: " + thread.getPriority());
    }
}

// 控制台显示如下:
Priority: 8

注: JVM为什么要单独用一个线程来执行finalize()方法呢?如果JVM的垃圾收集线程自己来做,很有可能由于在finalize()方法中误操作导致GC线程停止或不可控,这对GC线程来说是一种灾难

  • Reference Handler: JVM在创建main线程后就创建Reference Handler线程,其优先级最高,为10,它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题
for (Thread thread : Thread.getAllStackTraces().keySet()) {
    // 查看Reference Handler的线程优先级
    if ("Reference Handler".equals(thread.getName())) {
        System.out.println("Reference Handler Priority: " + thread.getPriority());
    }
}

// 控制台显示如下:
Reference Handler Priority: 10

2. 线程的六种状态

在Thread类源码中,State枚举,状态如下
在这里插入图片描述在这里插入图片描述

  1. NEW: 已经建立尚未启动的线程
  2. RUNNABLE: 在执行中的线程
  3. BLOCKED: 阻塞状态,线程在等待锁时为该状态
  4. WAITING: 等待状态,Object.wait(),Thread.join(),LockSupport.park这三个方法无参调用会使线程进入该状态
  5. TIMED_WAITING: 超时等待状态。等待另一个线程到达指定时间的等待状态,Object.wait()和Thread.join()方法的有参调用,Thread.sleep(),LockSupport.parkNanos,LockSupport.parkUntil方法会使线程进入该状态
  6. TERMINATED: 终止状态,代表线程已经完全执行完了

3. 线程池的五种状态

ThreadPoolExecutor类的源码中,有一段如下注释,读起来也很容易

 * The runState provides the main lifecycle control, taking on values:
 *
 *   RUNNING:  Accept new tasks and process queued tasks
 *   SHUTDOWN: Don't accept new tasks, but process queued tasks
 *   STOP:     Don't accept new tasks, don't process queued tasks,
 *             and interrupt in-progress tasks
 *   TIDYING:  All tasks have terminated, workerCount is zero,
 *             the thread transitioning to state TIDYING
 *             will run the terminated() hook method
 *   TERMINATED: terminated() has completed
  • 完整的线程池生命周期由以下五个状态控制
  • RUNNING:能接受新的任务,并且也能处理阻塞队列中的任务
  • SHUTDOWN:不再接收新提交的任务,但仍然处理存量任务
  • STOP:不再接受新提交的任务,也不处理存量任务并且会打断当前执行的任务
  • TIDYING:所有任务都终止
  • TERMINATED:执行terminated()方法执行完,进入该状态

4. wait() 和 sleep()的区别

  1. 原理不同。wait()是Object类的方法,用于线程通信。sleep()是Thread的静态方法,用于控制流程,让线程"睡觉",把执行的机会让给其他线程
  2. 使用的区域不同。wait()用于同步方法或同步代码块儿中。sleep()随处都可睡
  3. 对锁的处理也不同。wait()的时候就会把锁给释放了,而sleep()则会和锁一起睡觉,不会释放锁

5. synchronized 和 Lock 的区别

  1. synchronized 是内置的关键字;Lock是java的接口
  2. synchronized 可重入,不可中断,非公平;Lock 可重入,可判断,可公平
  3. synchronized 无法判断锁的状态;Lock可以判断锁的状态
  4. synchronized 会自动释放锁;Lock需要手动释放锁
  5. synchronized 会当线程获得锁并且阻塞的话,其他线程会一直等待;Lock不一定会一直等待下去,可以尝试获得锁(tryLock()方法),获取不到,就不再等待
  • ReentrantLock 构造函数源码
    在这里插入图片描述

6. 查看死锁问题的堆栈信息

  • 死锁发生的时候,我们可以通过jpsjstack命令来查看堆栈信息
    在这里插入图片描述
    在这里插入图片描述

  • 在堆栈信息中,我们可以发现 Found 1 deadlock 的死锁提示,以及发生死锁的具体信息


加油儿!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
[JAVA工程师必会知识点之并发编程]1、现在几乎100%的公司面试都必须面试并发编程,尤其是互联网公司,对于并发编程的要求更高,并发编程能力已经成为职场敲门砖。2、现在已经是移动互联和大数据时代,对于应用程序的性能、处理能力、处理时效性要求更高了,传统的串行化编程无法充分利用现有的服务器性能。3、并发编程是几乎所有框架的底层基础,掌握好并发编程更有利于我们学习各种框架。想要让自己的程序执行、接口响应、批处理效率更高,必须使用并发编程。4、并发编程高级程序员的标配,是拿高薪的必备条件。 【主讲讲师】尹洪亮Kevin:现任职某互联网公司首席架构师,负责系统架构、项目群管理、产品研发工作。10余年软件行业经验,具有数百个线上项目实战经验。擅长JAVA技术栈、高并发高可用伸缩式微服务架构、DevOps。主导研发的蜂巢微服务架构已经成功支撑数百个微服务稳定运行【推荐你学习这门课的理由:知识体系完整+丰富学习资料】1、 本课程总计122课时,由五大体系组成,目的是让你一次性搞定并发编程。分别是并发编程基础、进阶、精通篇、Disruptor高并发框架、RateLimiter高并发访问限流吗,BAT员工也在学。2、课程附带附带3个项目源码,几百个课程示例,5个高清PDF课件。3、本课程0基础入门,从进程、线程、JVM开始讲起,每一个章节只专注于一个知识点,每个章节均有代码实例。 【课程分为基础篇、进阶篇、高级篇】一、基础篇基础篇从进程与线程、内存、CPU时间片轮训讲起,包含线程的3种创建方法、可视化观察线程、join、sleep、yield、interrupt,Synchronized、重入锁、对象锁、类锁、wait、notify、线程上下文切换、守护线程、阻塞式安全队列等内容。二、进阶篇进阶篇课程涵盖volatied关键字、Actomic类、可见性、原子性、ThreadLocal、Unsafe底层、同步类容器、并发类容器、5种并发队列、COW容器、InheritableThreadLocal源码解析等内容。三、精通篇精通篇课程涵盖JUC下的核心工具类,CountDownLath、CyclicBarrier、Phaser、Semaphore、Exchanger、ReentrantLock、ReentrantReadWriteLock、StampedLock、LockSupport、AQS底层、悲观锁、乐观锁、自旋锁、公平锁、非公平锁、排它锁、共享锁、重入锁、线程池、CachedThreadPool、FixedThreadPool、ScheduledThreadPool、SingleThreadExecutor、自定义线程池、ThreadFactory、线程池切面编程、线程池动态管理等内容,高并发设计模式,Future模式、Master Worker模式、CompletionService、ForkJoin等课程还包含Disruptor高并发无锁框架讲解:Disruptor支持每秒600万订单处理的恐怖能力。深入到底层原理和开发模式,让你又懂又会用。高并发访问限流讲解:涵盖木桶算法、令牌桶算法、Google RateLimiter限流开发、Apache JMeter压力测试实战。 【学完后我将达到什么水平?】1、 吊打一切并发编程相关的笔试题、面试题。2、 重构自己并发编程的体系知识,不再谈并发色变。3、 精准掌握JAVA各种并发工具类、方法、关键字的原理和使用。4、 轻松上手写出更高效、更优雅的并发程序,在工作能够提出更多的解决方案。  【面向人群】1、 总感觉并发编程很难、很复杂、不敢学习的人群。2、 准备跳槽、找工作、拿高薪的程序员。3、 希望提高自己的编程能力,开发出更高效、性能更强劲系统的人群。4、 想要快速、系统化、精准掌握并发编程的人群。【课程知识体系图】

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方圆想当图灵

嘿嘿,小赏就行,不赏俺也不争你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值