【Java (10-2) 多线程学习】
创始人
2025-05-28 20:22:13
0

多线程学习

四、线程池&volatile

1. 线程状态

在这里插入图片描述
在这里插入图片描述

2. 线程池

线程池的原理类似于用碗吃饭,吃完后放回橱柜(就是线程池),如果这个碗正在使用(A线程),这时需要新的线程B执行,则从橱柜里重新拿碗,如果A线程使用的碗还未归还则需要拿新的碗进行吃饭;
在这里插入图片描述

3. 线程池-Executors

3.1 Executors.newCachedThreadPool();

//创建一个根据需要创建新线程的线程池,但在可用时将重新使用以前构造的线程。
//static ExecutorService newCachedThreadPool()
//创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的线程。
//static ExecutorService newFixedThreadPool(int nThreads)import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPool {public static void main(String[] args) throws InterruptedException {//创建一个默认线程池对象 默认是空的 默认最大是int的最大值ExecutorService executorService = Executors.newCachedThreadPool();//Executors 帮助我们创建线程池对象//ExecutorService 帮追我们管理线程池executorService.submit(()->{System.out.println(Thread.currentThread().getName()+"在执行了");});//  Thread.sleep(2000);executorService.submit(()->{System.out.println(Thread.currentThread().getName()+"在执行了");});executorService.shutdown();}}

此时之所以是两个线程执行因为线程1执行完还未归还线程池内时,线程2已经执行,所以时两个线程对象
执行结果
在这里插入图片描述

执行时后睡2s后执行,由一个线程对象执行的
在这里插入图片描述

3.2 Executors.newFixedThreadPool();

newFixedThreadPool(10) 这里的值 是线程池的最大值


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的线程。
//static ExecutorService newFixedThreadPool(int nThreads)
public class ThreadPool2 {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(10);executorService.submit(()->{System.out.println(Thread.currentThread().getName()+"在执行了");});executorService.submit(()->{System.out.println(Thread.currentThread().getName()+"在执行了");});executorService.shutdown();}
}//获取最大线程池容量import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;//创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的线程。
//static ExecutorService newFixedThreadPool(int nThreads)
public class ThreadPool2 {public static void main(String[] args) {//参数不是初始值 而是最大值ExecutorService executorService = Executors.newFixedThreadPool(10);ThreadPoolExecutor pool=(ThreadPoolExecutor) executorService;System.out.println(pool.getPoolSize());executorService.submit(()->{System.out.println(Thread.currentThread().getName()+"在执行了");});executorService.submit(()->{System.out.println(Thread.currentThread().getName()+"在执行了");});executorService.shutdown();System.out.println(pool.getPoolSize());}
}

4. 自定义线程池 -ThreadPoolExecutor

在这里插入图片描述
在这里插入图片描述
代码实现


//ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
// BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
//        创建一个新 ThreadPoolExecutor给定的初始参数。import java.util.concurrent.*;/**** 参数1:核心线程数量* 参数2:最大线程数* 参数3:空闲线程最大存活时间* 参数4:时间单位* 参数5:任务队列  如下最大执行为5个线程,超过5个线程时就要在队列中等待* 参数6:任务创建工厂 按照默认方式创建线程对象 源码中还是new Thread()* 参数7:任务拒绝策略  什么时候拒绝任务?  当提交任务>池子中最大线程数量+任务队列容量           怎样拒绝任务?? * 4种拒绝任务策略*/
public class ThreadPool3 {static class MyRunnable implements  Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"在执行了");}}public static void main(String[] args) {ThreadPoolExecutor pool=new ThreadPoolExecutor(2,5,2,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());pool.submit(new MyRunnable());pool.submit(new MyRunnable());pool.shutdown();}
}
4.1线程池任务拒绝策略

4.1.1 new ThreadPoolExecutor.AbortPolicy()

超过线程池中线程最大容量+任务队列容量时:丢弃任务并抛出异常

代码实现


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/**** 参数1:核心线程数量* 参数2:最大线程数* 参数3:空闲线程最大存活时间* 参数4:时间单位* 参数5:任务队列* 参数6:任务创建工厂* 参数7:任务拒绝策略*/
public class ThreadPool4 {static class MyRunnable implements  Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"在执行了");}}public static void main(String[] args) {ThreadPoolExecutor pool=new ThreadPoolExecutor(2,5,2,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());for (int i = 1; i <= 16; i++) {pool.submit(new MyRunnable());}pool.shutdown();}
}
4.1.2 new ThreadPoolExecutor.DiscardPolicy()

直接丢弃 不抛异常


public class ThreadPool4 {static class MyRunnable implements  Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"在执行了");}}public static void main(String[] args) {ThreadPoolExecutor pool=new ThreadPoolExecutor(1,2,2,TimeUnit.SECONDS,new ArrayBlockingQueue<>(1),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardPolicy());for (int i = 1; i <= 5; i++) {int y=i;pool.submit(()->{
System.out.println(Thread.currentThread().getName()+"*****"+y);});}pool.shutdown();}
}

执行结果:
在这里插入图片描述

4.1.3 new ThreadPoolExecutor.DiscardOldestPolicy()

抛弃队列中等待最久,加入当前任务进入队列
直接放结果
在这里插入图片描述

4.1.4 new ThreadPoolExecutor.CallerRunsPolicy()

在这里插入图片描述

5. volatile关键字

强制线程每次使用的时候,都会看一下共享区域最新的值
对 volatile 修饰的变量值,保证线程读取到的值是最新的,而不是寄存器中缓存的值。
在这里插入图片描述
在这里插入图片描述


class Money {public  static volatile  int money=100000;public static void main(String[] args) {MyThead1 t1=new MyThead1();MyThead2 t2=new MyThead2();t2.start();t1.start();}
}
class MyThead2  extends  Thread{
@Override
public void run() {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}Money.money=90000;}}public class MyThead1  extends  Thread{@Overridepublic void run() {while (Money.money==100000){}System.out.println("结婚基金已经不是10万了");}
}
5.1 synchronized解决

代码实现:


class Money {public static volatile int money = 100000;public static Object lock = new Object();public static void main(String[] args) {MyThead1 t1 = new MyThead1();MyThead2 t2 = new MyThead2();t2.start();t1.start();}
}class MyThead2 extends Thread {@Overridepublic void run() {synchronized (Money.lock){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}Money.money = 90000;}}
}public class MyThead1 extends Thread {@Overridepublic void run() {while (true) {synchronized (Money.lock) {if (Money.money != 100000) {System.out.println("结婚基金已经不是10万了");break;}}}}
}

原理:
在这里插入图片描述

相关内容

热门资讯

【MySQL】锁 锁 文章目录锁全局锁表级锁表锁元数据锁(MDL)意向锁AUTO-INC锁...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
GCN的几种模型复现笔记 引言 本篇笔记紧接上文,主要是上一篇看写了快2w字,再去接入代码感觉有点...
数据分页展示逻辑 import java.util.Arrays;import java.util.List;impo...
Redis为什么选择单线程?R... 目录专栏导读一、Redis版本迭代二、Redis4.0之前为什么一直采用单线程?三、R...
【已解决】ERROR: Cou... 正确指令: pip install pyyaml
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
Lock 接口解读 前置知识点Synchronized synchronized 是 Java 中的关键字,...
Win7 专业版安装中文包、汉... 参考资料:http://www.metsky.com/archives/350.htm...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
大模型未来趋势 大模型是人工智能领域的重要发展趋势之一,未来有着广阔的应用前景和发展空间。以下是大模型未来的趋势和展...
python实战应用讲解-【n... 目录 如何在Python中计算残余的平方和 方法1:使用其Base公式 方法2:使用statsmod...
学习u-boot 需要了解的m... 一、常用函数 1. origin 函数 origin 函数的返回值就是变量来源。使用格式如下...
常用python爬虫库介绍与简... 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库&...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
【2023-03-22】SRS... 【2023-03-22】SRS推流搭配FFmpeg实现目标检测 说明: 外侧测试使用SRS播放器测...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
初级算法-哈希表 主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-哈希表...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
【Docker】P3 Dock... Docker数据卷、宿主机与挂载数据卷的概念及作用挂载宿主机配置数据卷挂载操作示例一个容器挂载多个目...