JAVA基础-线程池

本文深入探讨了线程间的等待唤醒机制,包括生产者消费者模式、Java内存模型、可见性问题、volatile关键字、CAS算法以及线程池的使用。详细解析了线程状态转换、线程同步和并发控制的关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 线程间的等待唤醒机制
    线程之间的等待唤醒机制,也就是生产者消费者模式

      1.定义一个资源
      2.要有一个生产线程
      3.要有一个消费线程
      4.测试类
    

等待唤醒:
作为生产者来说,有了资源,等着,通知消费线程来消费
作为消费线程,消费完了资源,通知生产线程来生产

Object

Object方法功能
void wait()在其他线程调用此对象的notify()方法前,导致当前线程等待。
void wait(long timeout)在其他线程调用此对象的notify()方法,或者超过指定的时间量前,导致当前线程等待
void notify()唤醒在此对象监视器上等待的单个线程
void notifyAll()唤醒在此对象监视器上等待的所有线程
  • 内存可见性问题volatile

1.Java内存模型
想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的。
Java内存模型规定了所有的变量都存储在主内存中。每条线程中还有自己的工作内存,
线程的工作内存中保存了被该线程所使用到的变量(这些变量是从主内存中拷贝而来)。
线程对变量的所有操作(读取,赋值)都必须在工作内存中进行。
不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。

2.Java中的可见性
对于可见性,Java提供了volatile关键字来保证可见性。
当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,
当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,
并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
相较于 synchronized 是一种较为轻量级的同步策略。

volatile 变量,用来确保将变量的更新操作通知到其他线程。
可以将 volatile 看做一个轻量级的锁,但是又与
锁有些不同:
 对于多线程,不是一种互斥关系
 不能保证变量状态的“原子性操作”

在这里插入图片描述

  • CAS算法
    1.CAS (Compare-And-Swap) 是一种硬件对并发。的支持,针对多处理器
    操作而设计的处理器中的一种特殊指令,用于管理对共享数据的并
    发访问。
  1. CAS 是一种无锁的非阻塞算法的实现。
  2. CAS 包含了 3 个操作数:
  3. 需要读写的内存值 V
  4. 进行比较的值 A
  5. 拟写入的新值 B

当且仅当 V 的值等于 A 时, CAS 通过原子方式用新值 B 来更新 V 的
值,否则不会执行任何操作。
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。

在这里插入图片描述

  • 线程的状态转换图及常见执行情况

    新建 , 就绪 , 运行 , 冻结 , 死亡

    新建:线程被创建出来
    就绪:具有CPU的执行资格,但是不具有CPU的执行权
    运行:具有CPU的执行资格,也具有CPU的执行权
    阻塞:不具有CPU的执行资格,也不具有CPU的执行权
    死亡:不具有CPU的执行资格,也不具有CPU的执行权

  • 线程池的概述和使用

线程池概述:线程池是一个容器,它里面的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
内置线程池的使用概述:
有几个方法

方法名功能
public static ExecutorService newCachedThreadPool():根据任务的数量来创建线程对应的线程个数
public static ExecutorService newFixedThreadPool(int nThreads):固定初始化几个线程
public static ExecutorService newSingleThreadExecutor():初始化一个线程的线程池

这些方法的返回值都是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象的线程。它提供了以下方法
Future<?> submit(Runnable task)
Future submit(Callable task)
使用步骤:
创建线程池对象
创建Runnable实例
提交Runnable实例
关闭线程池

在这里插入图片描述
public static ExecutorService newCachedThreadPool这个是你创建多少个就会有多少个不同的线程在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 匿名内部类实现多线程

匿名内部类实现多线程,有两种方法。如果仅仅使用一次多线程的话,可以使用这个匿名内部类来实现
第一种
在这里插入图片描述
第二种
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值