java多线程使用与踩坑

SpringBoot使用多线程简单方法:地址
线程安全查阅资料参考:地址

背景: 经过上述资料查看,我想写个方法(依靠notify()唤醒,依靠wait()等待)实现两个线程轮流打印。

配置多线程方法1

实现:
1.线程池配置(配置完线程池后直接 @Async就可以异步调用注释的方法了)

@Configuration
@EnableAsync
public class AsyncConfiguration {@Bean("ceshiAsync")public Executor doSomethingExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 核心线程数:线程池创建时候初始化的线程数executor.setCorePoolSize(3);// 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程executor.setMaxPoolSize(4);// 缓冲队列:用来缓冲执行任务的队列executor.setQueueCapacity(10);// 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁executor.setKeepAliveSeconds(6);// 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池executor.setThreadNamePrefix("测试线程-");// 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程)
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());executor.initialize();return executor;}}

2.轮流打印的方法(此次是测试锁与多线程使用)( 两个方法完全一样,主要依靠list.notify(); list.wait();)

@Async("ceshiAsync")public void aaa(List<Integer> list) {System.out.println("线程A等待获取i锁");synchronized (list) {try {System.out.println("线程A获取了i锁");while (list.get(0)>-1){log.info("线程A:"+list.get(0));list.set(0,list.get(0)-1);list.notify();list.wait();}} catch (Exception e) {e.printStackTrace();}}}@Async("ceshiAsync")public void bbb(List<Integer> list) {System.out.println("线程B等待获取i锁");synchronized (list) {try {System.out.println("线程B获取了i锁");while (list.get(0)>-1){log.info("线程B:"+list.get(0));list.set(0,list.get(0)-1);list.notify();list.wait();}} catch (Exception e) {e.printStackTrace();}}}

3.调用方法

List<Integer> list=new ArrayList<>();@Test@GetMapping(value = "ccc")public void ccc(){list.add(100);ceshiService.aaa(list);System.out.println("-----------");ceshiService.bbb(list);}

实现效果
在这里插入图片描述
在这里插入图片描述
踩坑

1.@Async注解未生效
原因:测试图方便把注解的方法直接写在方法,调用时直接用方法名调用,固注解未生效,这种写法会导致注解失效,例如事务的注解,但是与事务不同的时注入自身时记得添加 @Lazy注解,避免循环依赖。
在这里插入图片描述

2.current thread is not owner(当前线程不是所有者)错误
不要直接用Integer对象当锁,查询资料Integer内部的int值是不可改变的,估计是值改变时地址变了导致报这个错。

3.执行到一半报错
效果:在这里插入图片描述
原因:有些测试不适合用@Test注解,例如这里线程池出问题,事后想想这报错完全是理所应当的事情,亏我还在怀疑是notify方法提前把锁释放了导致wait执行时没锁了。罪过罪过

配置多线程方法2

实现:
1.线程池配置(使用时ScheduledAsync.getThreadPool().submit(() -> 要执行的方法;),对比第一种优点是对于已经写好的业务不用把需要异步执行的部分单独拿出来加注解,Runtime.getRuntime().availableProcessors();是获取可用的计算资源。

@Configuration
@EnableAsync
public class ScheduledAsync{public static final int CPU_NUM = Runtime.getRuntime().availableProcessors();private static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CPU_NUM, CPU_NUM,1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(CPU_NUM + 10));static {// 设置拒绝策略threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 空闲队列存活时间threadPool.setKeepAliveTime(20, TimeUnit.SECONDS);}public static ThreadPoolExecutor getThreadPool(){return threadPool;}}

阻塞的使用

若希望前面一段代码都执行完再统一执行下边可以使用CountDownLatch进行阻塞
例如代码

List<String> aaas= Arrays.asList("1111","2222","3333","4444");aaas.forEach(aaa-> {ScheduledAsync.getThreadPool().submit(() -> {System.out.println("------------执行"+aaa);try {Thread.sleep(2000);System.out.println("------------休眠后执行"+aaa);} catch (InterruptedException e) {throw new RuntimeException(e);}});});System.out.println("循环外");

在这里插入图片描述

添加阻塞后:

List<String> aaas= Arrays.asList("1111","2222","3333","4444");CountDownLatch countDownLatch = new CountDownLatch(aaas.size());//设定一个数目aaas.forEach(aaa-> {ScheduledAsync.getThreadPool().submit(() -> {System.out.println("------------执行"+aaa);try {Thread.sleep(2000);System.out.println("------------休眠后执行"+aaa);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {countDownLatch.countDown();//可理解为计数器+1}});});countDownLatch.await();//达到设定数目后执行System.out.println("循环外");

效果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/557638.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学成在线_视频处理_视频转码不成功

问题 当我们用xxljob进行视频处理中的转码操作时会发现视频转码不成功。即程序会进入下图所示的if语句内。 问题原因 在进行视频转码时程序会调用Mp4VideoUtil类下的 generateMp4方法&#xff0c;而result接收的正是该方法的返回值。那么什么时候generateMp4方法的返回值会…

个性化影片推荐系统|基于JSP技术+ Mysql+Java+ Tomcat的个性化影片推荐系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

html5cssjs代码 034 自定义字体

html5&css&js代码 034 自定义字体 一、代码二、解释 这是一个带有自定义字体的网页&#xff0c;设置了页面背景颜色、文字颜色以及全局样式。它定义了三种自定义字体并通过font-face规则引入外部字体文件&#xff0c;并通过CSS类&#xff08;.f1, .f2, .f3&#xff09;…

基于Python3的数据结构与算法 - 16 链表

目录 链表 1. 创建链表 2. 链表的插入和删除 3. 双链表 4. 链表总结 链表 链表是由一系列节点组成的元素集合。每个节点包含两部分&#xff0c;数据域item和指向下一个节点得指针next。通过节点之间的相互连接&#xff0c;最终串联成一个链表。 class Node:def __init…

SpringCloudGateway之高性能篇

SpringCloudGateway之高性能篇 背景 在公司的开放平台中&#xff0c;为了统一管理对外提供的接口、处理公共逻辑、实现安全防护及流量控制&#xff0c;确实需要一个API网关作为中间层。 场景 统一接入点: API网关作为所有对外服务的单一入口&#xff0c;简化客户端对内部系统…

《区块链技术:解锁数字时代的无限可能》

区块链技术作为近年来备受瞩目的创新技术&#xff0c;正以崭新的姿态改变着我们的世界。从技术进展到行业应用&#xff0c;再到面临的挑战与机遇&#xff0c;以及未来的发展趋势&#xff0c;本文将全面剖析区块链技术的发展现状和潜力。 区块链技术原理 区块链技术原理是指构成…

智慧公厕的系统构成与功能解析

智慧公厕系统是通过传感器和云平台相结合的创新技术&#xff0c;旨在提供更好的公厕管理与服务。智慧公厕从系统的构成来看&#xff0c;主要分为感知层&#xff08;数据收集&#xff09;、传输层&#xff08;数据传输&#xff09;、平台层&#xff08;数据处理&#xff09;和应…

Ubuntu学习笔记之Shell与APT下载工具

基本都是摘抄正点原子的文章&#xff1a;<领航者 ZYNQ 之嵌入式Linux 开发指南 V3.2.pdf&#xff0c;因初次学习&#xff0c;仅作学习摘录之用&#xff0c;有不懂之处后续会继续更新~ 一、Ubuntu Shell操作 简单的说Shell 就是敲命令。国内把 Linux 下通过命令行输入命令叫…

4、类加载器

2.4.1 什么是类加载器 类加载器&#xff08;ClassLoader&#xff09;是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术&#xff0c;类加载器只参与加载过程中的字节码获取并加载到内存这一部分。 类加载器会通过二进制流的方式获取到字节码文件的内容&#xff0c…

【算法】数组-移除元素

给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的…

CentOS、windows与Server_u服务器之间加密传输

一、适用场景&#xff1a; 1、保护数据传输&#xff1a;使用FTPS&#xff08;FTP over SSL/TLS&#xff09;可以加密FTP会话中的所有数据&#xff0c;从而防止数据在网络中被监听或篡改。 2、符合安全标准&#xff1a;许多行业标准要求数据传输必须是加密的。 3、保护用户凭证…

阿里云云服务器ECS端口多个端口号开通教程

阿里云云服务器ECS端口多个端口号开通教程 1、登录到ECS云服务器管理控制台 2、左侧栏找到【实例与镜像】>>【实例】&#xff0c;找到目标ECS实例&#xff0c;点击实例ID进入到实例详情页 3、切换到【安全组】页面&#xff0c;点击右侧【配置规则】&#xff0c;如下图&…