免费注册
流程类
图形化表达方式
脑图类
结构化表达方式
笔记类
高效化表达方式
软件与系统设计
UML
工程与技术设计
数据分析与研究
其他图形
自由结构
树形图
括号图
默认模式

java多线程从入门到精通满满的干货

ProcessOn阳光 2月前
238
ProcessOn,立刻提升你的工作效率
首页 知识社区 java多线程从入门到精通满满的干货

java线程的说明

学习线程之前需要了解两个知识点,一个是进程,一个是线程

  • 进程: 是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
  • 线程: 是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

java线程的五种状态 Java中线程的五种状态是: 新建(New), 可运行(Runable), 运行(Running), 阻塞(Blocked), 死亡(Dead). 但是Java没有给我们提供直接获取线程死亡状态的方法,因为一旦线程死亡,它的状态信息就会丢失,因为它可能会被垃圾收集器回收。

  • 新建状态: 当线程对象对创建后,例如Thread t = new Thread(),但是还没有开始运行,这是线程处于新建状态。
  • 可运行状态:当调用线程的start()方法后,例如t.start(),线程进入可运行状态。此时它在等待获取CPU的使用权,一旦获取,它就处于运行状态。
  • 运行状态: 当线程获取CPU使用权后,它就进入运行状态,开始执行run()方法的内容。
  • 阻塞状态:一个正在运行的线程如果调用了sleep(), wait(), join()或者是等待I/O操作,那么它将进入阻塞状态,这是它会放弃CPU使用权,暂时停止运行。当阻塞解除后,它会回到可运行状态。阻塞的情况分三种: (1)、等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。(2)、同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。(3)、其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

死亡状态: 线程运行结束后,或者被提前强制结束,那么它就处于死亡状态。

线程状态变化图

ThreadLocal的说明及使用

ThreadLocal是Thread的局部变量,是每个线程特有的,其它线程不能对其进行访问,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。

ThreadLocal结构

threadlocal的详细说明

java锁的几种实现方式

在Java中,锁(Lock)是一种用于控制多个线程对共享资源的访问的机制。通过锁,可以确保同一时间只有一个线程能够访问某个特定的代码块或资源,从而避免数据的不一致性和其他并发问题。当一个线程想要访问共享资源时,它必须先获取锁。如果锁已经被另一个线程持有,则该线程将被阻塞,直到锁被释放。一旦线程获取了锁,它就可以安全地访问共享资源,而不用担心其他线程会同时访问并导致数据冲突。当线程完成对共享资源的访问后,它必须释放锁,以便其他线程可以使用它。

使用synchronized关键字

synchronized是Java中内置的锁机制,可以修饰方法或者代码块。当一个线程试图进入一个synchronized方法或代码块时,它必须先获得锁。如果锁已经被其他线程持有,则该线程将被阻塞,直到锁被释放。

使用ReentrantLock类

 它是一个可重入锁,通过调用lock()和unlock()方法获取和释放锁。与synchronized不同,ReentrantLock提供了更灵活的同步控制,例如可实现公平性和试锁等待时间。

使用wait()、notify()和notifyAll()方法

这些方法是Object类的方法,允许线程间进行协作和通信。通过调用wait()方法使线程进入等待状态,然后其他线程可以通过notify()或notifyAll()方法唤醒等待的线程。

使用CountDownLatch和CyclicBarrier

它们是并发工具类,用于线程之间的同步和等待。CountDownLatch可用于等待一组线程完成操作,而CyclicBarrier用于等待一组线程互相达到屏障位置。

Java锁---一图秒懂

java 线程池

 线程池顾名思义就是用来存放线程的池子,用来管理和复用线程。由于频繁的创建和销毁线程,比较耗费资源,为减少开销,所以出现了线程池。线程池可以有效的管理其中线程的生命周期、调度和执行。可以动态的给其中的线程分配任务去执行。

线程池主要分为以下几类:

  1. FixedThreadPool(固定大小线程池):固定大小线程池中包含固定数量的线程,当有任务提交时,线程池中没有空闲线程时,任务会被放入任务队列中等待执行。这种线程池适用于需要限制并发线程数量的场景。
  2. CachedThreadPool(缓存线程池):缓存线程池不固定线程数量,可以根据需要自动创建新线程,当线程空闲时间超过设定的时间(默认60s)会被回收,适用于短期异步任务。
  3. SingleThreadPool(单线程池):单线程池只包含一个工作线程,保证所有任务按顺序执行。适用于需要保持任务顺序执行的场景。
  4. ScheduledThreadPool(定时线程池):这种线程池可以执行定时任务和周期性任务。它继承自ExecutorService,并通过 ScheduledExecutorService 接口提供定时任务功能。
  5. WorkStealingPool(工作窃取线程池):这是Java 8中引入的一种新类型的线程池,主要用于处理耗时任务。它适用于需要大量并行任务、任务之间没有依赖关系的情况。
  6. CustomThreadPool(自定义线程池):除了以上内置的线程池类型,开发人员也可以根据实际需求自定义线程池,通过配置线程池的参数来适应特定的业务场景。 这些线程池类型允许开发人员根据不同的场景和需求选择适合的线程池,从而提高多线程程序的性能和效率。在实际应用中,根据任务的特性和线程池的负载情况选择适当的线程池类型非常重要。

主要的参数

  • 核心线程数(Core Pool Size) 核心线程数是线程池中一直存活的线程数量(即使它们处于空闲状态)。这些线程用于执行提交到线程池的任务。通过合理设置核心线程数,可以在系统负载增加时迅速响应任务。
  • 最大线程数(Maximum Pool Size) 最大线程数定义了线程池中允许创建的最大线程数量。当核心线程都在执行任务,而新任务仍然到来时,线程池会创建新线程,直到达到最大线程数。超过最大线程数的任务会被拒绝。
  • 线程存活时间(Keep Alive Time) 线程存活时间指的是非核心线程在空闲状态下的最大存活时间。当线程池中线程数量超过核心线程数时,空闲的非核心线程在经过一定时间后会被终止,从而释放系统资源。
  • TimeUnit keepAliveTime的单位(ms、s…)
  • 工作队列(Work Queue) 工作队列用于存放等待执行的任务。不同类型的队列对线程池的行为有重要影响,例如有界队列和无界队列。有界队列在任务数达到上限时会触发拒绝策略。
  • ThreadFactory 线程池中生成线程的工厂。默认使用默认工厂Executors.defaultThreadFactory()。但是实际使用时建议使用Guava的ThreadFactory自定义线程的名字,方便排查线程问题(阿里开发规范中也建议这么做)。如下:

 ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("mythread-pool-").build();

  • 拒绝策略(Rejected Execution Policy) 拒绝策略定义了当工作队列满,并且当前工作的线程数等于最大线程数时,后续再提交的任务如何处理。例如,可以选择抛弃任务、抛出异常或在调用线程中直接执行。Java线程池提供了几种常见的拒绝策略:
  • AbortPolicy(默认策略): 直接抛出RejectedExecutionException,阻止系统继续接受新任务,保持原有状态。 new ThreadPoolExecutor.AbortPolicy();CallerRunsPolicy: 将任务返回给调用者,由调用线程直接执行。 new ThreadPoolExecutor.CallerRunsPolicy();DiscardPolicy: 直接丢弃无法处理的任务,不抛出异常。 new ThreadPoolExecutor.DiscardPolicy();DiscardOldestPolicy: 当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。 new ThreadPoolExecutor.DiscardOldestPolicy();

Java线程池工作原理

Java之线程池

以上图片内容来自ProcessOn 模板社区,你可以点击此链接查看详情。如果你想要将自己的知识结构化记录下来,ProcessOn 是你的绝佳选择,提供多种专业图形的绘制工具和丰富的模板内容,支持工作、学习和生活各个方面的应用。

免费在线协同思维导图流程图 免费使用