多线程学习
并发:交替运行
并行:一起运行
多线程实现方式
继承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…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
