多线程学习
并发:交替运行
并行:一起运行
多线程实现方式
继承Thread类
①自己定义一个类继承Thread
public class MyThread extends Thread{public void run(){}}
②重写run方法
public class MyThread extends Thread{public void run(){"重写的内容"}}
③创建子类对象,并启动线程
MyThread t1 = new MyThread();
t1.setName("线程1的名字");
t1.start("开始运行线程1");
实现Runnable接口
①自己定义一个类实现Runnable接口
public class MyRun implements Runnable{public void run(){}
}
②重写里面的run方法
public class MyRun implements Runnable{public void run(){"重写的代码"}
}
注意:在重写run的过程中是不能调用getName这个方法的,因为使用的是自己创建的类,如果要使用的话,可以用Thread t = Thread.currentThread();就相当于返回的是相应线程的对象
③创建自己的类的对象
Myrun mr = new Myrun();
④创建一个Thread类的对象
Thread t1 = new Thread(mr);
利用Callable接口和Future接口(可以获取到多线程运行的结果)
①创建一个类MyCallable实现Callable接口
public class MyCallable implements Callable<V>{public V call(){return V;}
}
②重写call(有返回值)
③创建MyCallable的对象(表示多线程要执行的任务)
MyCallable mc = new MyCallable();
④创建FutureTask的对象(作用管理多线程运行的结果)
//管理Callanle
FutureTask<V> ft = new FutureTask<>(mc);
⑤创建Thread类的对象,并启动
Thread t1 = new Thread(ft);
t1.start();
V result = ft.get();//获取结果
常见的成员方法
setName()
注意:
- 如果没有给线程设置名字,线程也是有默认名字的
- 如果我们要给线程设置名字,可以用set方法进行设置,也可以用构造方法设置
currentsThread()
- 当JVM虚拟机启动之后,会自动的启动多个线程,其中有一条叫做main线程,它的作用就是去调用main方法,并执行里面的代码
sleep()
- 哪条线程执行到这个方法,那么那条线程就要在这停留相应的时间
- 方法的参数:就表示这个停留的时间,单位毫秒
- 当时间到了之后,线程就会自动醒来,继续执行下面的代码
setPriority(); -----设置优先级
线程的调度(抢占CPU)
抢占式调度:随机性
非抢占式调度
setDeamon() ----- 设置守护线程
当其他线程都结束之后,守护线程也随之结束
例子:如果在聊条过程中,一边发送信息,一边发送文件,当关闭了发送信息的窗口的时候,那么文件也没必要发送,就结束发送文件这个线程
yield() ------ 礼让逻辑
作用,尽可能让各个线程执行的次数均匀
join() ------- 加入线程
线程的生命周期
线程的安全
同步代码块
容易出现问题的原因:在线程执行的时候,有随机性
解决:如果能把线程操作共享数据的代码锁起来,只让一条线程执行,这条线程执行完之后才能让下一条线程执行代码
关键字:synchronized(锁对象){操作共享的数据}
public class MyThread extends Thread{//static保证锁对象是唯一的
//创建一个任意的锁对象
static Object obj = new Object();synchronized(obj){操作代码}
}
特点:
- 锁默认打开,有一个线程进去了,锁自动关闭
- 里面的代码全部执行完毕,线程出来,锁自动打开
同步方法
特点:
- 同步方法是锁定方法里面的所有代码
- 锁对象不能自己指定
//Ctrl + Alt + m 将代码块抽取成方法
Lock锁
可以手动上锁和释放锁
lock();上锁
unlock();释放锁
死锁(错误)
不要让俩个锁嵌套使用
生产者和消费者(等待唤醒机制)
消费者等待
首先是消费者抢到了CPU的执行权
消费者
- 判断是否生产者生产了数据
- 如果没有就等待(wait)
生产者
- 生产数据
- 制作数据
- 叫醒消费者消费数据(notify)
生产者等待
俩次都是生产者抢到了CPU的执行权
生产者
- 判断是否现在是否生成了数据
- 有:等待
- 没有:生产数据
- 把数据放着
- 叫消费者消费数据
消费者
- 判断是否有数据可以消费
- 没有就等待
- 有就开始消费
- 没有就叫生产者开始生产
常用方法
解决方案
阻塞队列方式实现
生产者和消费者一定要使用一个阻塞队列
take()----获取
put()-----放入
注意:这俩个方法的底层都是上了锁的,不用再格外的去加锁
代码表示
厨师(生产者)
package com.FC;import java.util.concurrent.ArrayBlockingQueue;public class Cook extends Thread{ArrayBlockingQueue<String> queue;public Cook(ArrayBlockingQueue<String> queue){this.queue = queue;}public void run(){while(true){try {queue.put("面条");System.out.println("厨师放了一碗面条");} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
吃货(消费者)
package com.FC;import java.util.concurrent.ArrayBlockingQueue;public class Foodie extends Thread{ArrayBlockingQueue<String> queue;public Foodie(ArrayBlockingQueue<String> queue){this.queue = queue;}public void run(){while(true){try {String food = queue.take();System.out.println("我吃了一碗面条");} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
运行代码
package com.FC;import java.util.concurrent.ArrayBlockingQueue;public class ThreadDemo {public static void main(String[] args) {//创建阻塞队列的对象ArrayBlockingQueue<String > queue = new ArrayBlockingQueue<>(1);//创建线程Cook c = new Cook(queue);Foodie f = new Foodie(queue);//给线程设置名字c.setName("厨师");f.setName("吃货");//开启线程c.start();f.start();}
}
线程的状态
线程池
当有任务出现的时候,如果线程池里面为空,就创建一个新的线程,用于执行这个任务,执行完之后,把这个线程放到线程池里面,当下一个任务出现的时候,就不用创建新的线程了,直接从线程池里面拿现成的线程执行任务
用工具类实现
1.创建一个池子
//没有上限的线程池
public static ExecutorService newCachedThreadPool();
//有上限的线程池
public static ExecutorService newFixedThreadPool(int nThreads);
ExecutorService pool1 = Executors.newCachedThreadPool();
2.提交任务
pool1.submit(new MyRunnable());
3.所有的任务全部执行完毕之后,关闭线程池
pool1.shutdown();
自定义实现
自定义线程池中有核心线程和临时线程(都有一定的数量),当有很多任务要进行的时候,核心线程先进行一部分,然后一些任务排在队列里面(有一定的长度),当队列排满了之后,才会创建临时线程。
如果核心线程加上临时线程再加上队伍的长度都小于要执行的任务,那么默认会采用抛弃策略
ThreadPoolExecutor pool = new ThreadPoolExecutor(3,//核心线程数,不能小于06,//最大线程数,不能小于0,且要大于等于核心线程数60,//空闲线程最大存活时间TimeUnit.SECONDS,//时间单位new ArrayBlockingQueue<>(3),//任务队列Executors.defaultThreadFactory(),//创建线程工厂new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略);
其他
获取电脑的可用的处理器数目
int count = Runtime.getRuntime().availableProcessors();
线程池大小的定夺
相关文章:

多线程学习
并发:交替运行 并行:一起运行 多线程实现方式 继承Thread类 ①自己定义一个类继承Thread public class MyThread extends Thread{public void run(){}} ②重写run方法 public class MyThread extends Thread{public void run(){"重写的内容&…...

软件测试/测试开发丨ChatGPT在测试计划中的应用策略
点此获取更多相关资料 简介 测试计划是指描述了要进行的测试活动的范围、方法、资源和进度的文档。它主要包括测试项、被测特性、测试任务和风险控制等。 所以在使用ChatGPT输出结果之前,我们需要先将文档的内容框架梳理好,以及将内容范围划定好&…...

链表oj3(Leetcode)——相交链表;环形链表
一,相交链表 相交链表(Leetcode) 1.1分析 看到这个我们首先想到的就是一个一个比较他们的值有相等的就是交点,但是如果a1和b2的值就相等呢?所以这个思路不行,第二种就是依次比较链表,但是这…...

nginx反向代理
nginx反向代理8.反向代理8.1 实现http反向代理8.1.1 反向代理配置参数8.1.2 反向代理单台web服务器8.1.2.1 端口号后加"/"8.1.2.2 端口号后不加"/" 8.1.3指定location 实现反向代理,动静分离8.1.4 反向代理实例:缓存功能8.1.4.1 举例 8.1.5 实现…...

基于eBPF的安卓逆向辅助工具——stackplz
前言 stackplz是一款基于eBPF技术实现的追踪工具,目的是辅助安卓native逆向,仅支持64位进程,主要功能如下: hardware breakpoint 基于pref_event实现的硬件断点功能,在断点处可读取寄存器信息,不会被用户…...

十大排序——4.堆排序
前面我们讲了堆,现在我们来看一下队排序。 堆排序的步骤: 首先将一个无序数组建立成一个大顶堆然后,将堆顶的元素和堆低的元素进行交换(即将最大的元素交换的到堆底),缩小并下潜调整堆重复上一步…...

独辟蹊径”之动态切换进程代理IP
前言 项目中遇到这样一个需求,需要动态切换指定进程Sockets5代理IP,目前了解到可通过编写驱动拦截或者劫持LSP实现,LSP劫持不太稳定,驱动无疑是相对较好的解决方案,奈何水平不足便有了这"蹊径"。 初步尝试…...

redis漏洞修复:(CNVD-2019-21763)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、漏洞内容二、镜像准备1.确认镜像版本2.下载镜像 三、配置文件准备1.获取配置文件2.修改配置文件 四、启动redis容器五、修改iptables文件总结 前言 漏扫发…...

手刻 Deep Learning -第壹章-PyTorch入门教学-基础概念与再探线性回归
一、前言 本章会需要 微分、线性回归与矩阵的基本观念 这次我们要来做 PyTorch 的简单教学,我们先从简单的计算与自动导数( auto grad / 微分 )开始,使用优化器与误差计算,然后使用 PyTorch 做线性回归,还有…...

深入学习 Redis - 如何使用 Redis 作缓存?缓存更新策略?使用需要注意哪些问题(工作/重点)
目录 一、Redis 作为缓存 1.1、缓存的基本概念 1.1.1、理解 1.1.2、缓存存什么样的数据?二八定律 1.2、如何使用 redis 作为缓存 1.3、缓存更新策略(redis 内存淘汰机制 / 重点) 1.3.1、定期生成 1.3.2、实时生成 内存淘汰策略&#…...
好用的软件测试框架有哪些?测试框架的作用是什么?
软件测试框架是现代软件开发过程中至关重要的工具,它可以帮助开发团队更加高效地进行测试和验证工作,从而大大提高软件质量和用户体验。 一、好用的软件测试框架 1. Selenium:作为一种开源的自动化测试框架,Selenium具有功能强大…...

PAT 1035 插入与归并
PAT 1035 插入与归并 题目描述思路讲解代码展示 题目描述 思路讲解 分析:先将i指向中间序列中满足从左到右是从小到大顺序的最后一个下标,再将j指向从i1开始,第一个不满足a[j] b[j]的下标,如果j顺利到达了下标n,说明…...
K-means 聚类算法学习笔记
K-means 聚类算法 是一种无监督学习算法,用来将 n n n 个样本点分成 k k k 类,使得整个数据集的误差平方和 S S E SSE SSE 最小。在本例中,样本点是指平面直角坐标系上的点,聚类中心也是平面直角坐标系上的点,而每个…...

API文档搜索引擎
导航小助手 一、认识搜索引擎 二、项目目标 三、模块划分 四、创建项目 五、关于分词 六、实现索引模块 6.1 实现 Parser类 6.2 实现 Index类 6.2.1 创建 Index类 6.2.2 创建DocInfo类 6.2.3 创建 Weight类 6.2.4 实现 getDocInfo 和 getInverted方法 6.2.5 实现 …...

文案内容千篇一律,软文推广如何加深用户印象
随着互联网技术的发展,企业营销的方式逐渐转向软文推广,但是现在软文推广的内容同质化越来越严重,企业应该如何让自己的软文推广保持差异性,在用户心中留下独特的印象呢?下面就让媒介盒子告诉你。 一、 找出产品独特卖…...

十二、流程控制-循环
流程控制-循环 1.while循环语句★2.do...while语句★3.for循环语句 —————————————————————————————————————————————————— 1.while循环语句★ while语句也称条件判断语句,它的循环方式是利用一个条件来控制是否…...

五、回溯(trackback)
文章目录 一、算法定义二、经典例题(一)排列1.[46.全排列](https://leetcode.cn/problems/permutations/description/)(1)思路(2)代码(3)复杂度分析 2.[LCR 083. 全排列](https://le…...

什么是分布式锁?他解决了什么样的问题?
相信对于朋友们来说,锁这个东西已经非常熟悉了,在说分布式锁之前,我们来聊聊单体应用时候的本地锁,这个锁很多小伙伴都会用 ✔本地锁 我们在开发单体应用的时候,为了保证多个线程并发访问公共资源的时候,…...

Ubuntu 12.04增加右键命令:在终端中打开增加打开文件
Ubuntu 12.04增加右键命令:在终端中打开 软件中心:搜索nautilus-open-terminal安装 用快捷键CtrlT打开命令行输入: sudo apt-get install nautilus-open-terminal 重新加载文件管理器 nautilus -q 或注销再登录即要使用...
Centos 7 访问局域网windows共享文件夹
Refer: centos7 访问windows系统的共享文件夹_centos访问windows共享_三希的博客-CSDN博客 一、在CentOS中配置CIFS网络存储服务 CIFS(Common Internet File System)是一种在网络上共享文件的协议,也称为SMB(Server Message Blo…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...