当前位置: 首页 > news >正文

Java:多线程

多线程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。

并发和并行

并发:在同一时刻,有多个指令在单个CPU上交替执行

并行:在同一时刻,有多个指令在多个CPU上同时执行

实现方式

1·继承Thread类的方式进行实现

*多线程的第一种启动方式:

1.自己定义一个类继承Thread

2.重写run方法

3.创建子类的对象,并启动线程

2·实现Runable接口的方式进行实现

多线程的第二种启动方式:

1.自己定义一个类实现Runnable接口

2.重写里面的run方法

3.创建自己的类的对象

4.创建一个Thread类的对象,并开启线程

3·利用Callable接口和Future接口方式实现

1.创建一个类Mycallable实现callable接口
2.重写call(是有返回值的,表示多线程运行的结果)


3.创建Mycallable的对象(表示多线程要执行的任务)

4.创建Futureask的对象(作用管理多线程运行的结果)

5.创建Thread类的对象,并启动(表示线程)

三种方法的区别

Thread中常见的成员方法

线程优先级从1到10; 越低优先级越高

守护线程setDaemon

当其他非守护线程结束时候,守护线程就会陆续结束

出让线程/礼让线程

如果运行两个MyThread类对象则会,会使结果更加均匀,当运行到Thread.yield();就会把使用权让出去,重新分配

插入线程/插队线程

插入线程在某个线程中调用其他线程的jion方法,就会先把其他线程执行完

线程的生命周期

线程安全问题

在多个线程操作同一个数据时有时候会出现问题,问题是由线程执行顺序的随机引起的。

例如:

构造一类用来实现多个窗口的售票

再创建多个窗口来进行多个线程同时售票

结果出现了重复票和顺序和多票的问题,因为每个线程执行到每一步时候,执行权都有可能会被其它线程抢走,导致出现混乱

这时可以用同步代码块,让每一个线程都要执行完某一步骤执行权力才能让出去

同步代码块

把操作共享数据的代码锁起来

锁对象可以是任意的,但一定是唯一的

例如:static Object obj = new Object();(唯一的静态类)

MyThread.class (字节码文件对象,一定是唯一的)

就可以当作锁

特点1:锁默认打开,有一个线程进去了,锁自动关闭

特点2:当里面的代码都执行完毕,线程出来,锁自动打开,线程才可以进去

同步方法

就是把synchronized关键字加到方法上

格式:

特点1:同步方法是锁住方法里面所有的代码

特点2:锁对象不能自己指定:1·如果是静态方法锁对象就是当前方法的调用者:this 2·如果是静态方法,锁对象就是当前类的字节码文件对象

Lock锁

虽然我们可以理解同步代码块和同步方法的锁对象问题

但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,

为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作

Lock中提供了获得锁和释放锁的方法

void lock();获得锁

void unlock();释放锁

Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化ReentrantLock的构造方法

ReentrantLock(); 创建一个ReentrantLock的实例

死锁

是一种错误,当线程A拿到A锁的同时,线程B也拿到B锁了,就会导致A、B锁都锁了,线程A停在达到B锁这里,而线程B也无法拿到A锁

等待唤醒机制(生产者和消费者)

生产者和消费者模式是一个十分经典的多线程协作的模式

Java中的等待唤醒机制是一种线程间的通信方式,通过 Object 的 wait() 、 notify() 和 notifyAll() 方法来实现。

 
- 当一个线程执行到 wait() 方法时,它会释放当前持有的对象锁,并进入等待状态,直到其他线程调用 notify() 或 notifyAll() 方法来唤醒它。
 
-  notify() 方法会随机唤醒一个在该对象上等待的线程,而 notifyAll() 方法则会唤醒所有在该对象上等待的线程。被唤醒的线程不会立即执行,而是要等到调用 notify() 或 notifyAll() 方法的线程释放锁后,才会去竞争锁,获取到锁后才能继续执行。


用阻塞队列实现

线程的六种状态

线程池

主要原理:

1·创建一个池子,池子中是空的

2·提交任务时,池子就会创建新的线程对象,任务执行完毕,线程归还给池子,下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可

3·但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待
 

Executors:线程池的工具类通过调用方法返回不用类型的线程池对象。

1·创建一个没有上线的线程池

2·创建一个最多可以创建3个线程的线程池

自定义线程池

安排任务的顺序

1·先使用核心线程的数量来运行任务

2·诺核心线程数量小于要运行的任务,剩余任务则在阻塞队列排队

3·诺还添加任务到阻塞队列都装不下了,就会将后面装不下的任务交给:“线程池中最大线程数量 - 核心线程数量”的线程处理。也就是说后面的任务会先被其他线程处理(除了核心线程的),而阻塞队列中的任务就接着排队

4·诺线程池中最大的线程数量都已经被使用了,那么就会抛弃再加入的任。

5·诺“线程池中最大线程数量 - 核心线程数量”,已经被弃用“用TimeUnit”指定的时间那么就会从线程池中删除

线程池的拒绝策略

线程池大小选择

1·CPU密集型运算

CPU运行比较多,读取文件较少:最大并行数+1

2·I/O密集型运算

读取文件较多:

http://www.xdnf.cn/news/64549.html

相关文章:

  • C#处理网络传输中不完整的数据流
  • Maxscript调用Newtonsoft.Json解析Json
  • 制作一款打飞机游戏13:状态机
  • 广州可信数据空间上线:1个城市枢纽+N个产业专区+高质量数据集(附28个数据集清单)
  • 如何建设企业级合成数据中台?架构设计、权限治理与复用机制全解
  • 第 3 篇:揭秘时间模式 - 时间序列分解
  • OpenCV基础函数学习4
  • 【油藏地球物理正演软件ColchisFM】ColchisFM正演软件在阿姆河右岸区块礁滩复合体识别中的应用
  • transformer
  • 【Docker-16】Docker Volume存储卷
  • android 多个viewmodel之间通信
  • Android 最简单的native二进制程序
  • 【MySQL】:数据库事务管理
  • 深入理解路由器、IP地址及网络配置
  • 你的大模型服务如何压测:首 Token 延迟、并发与 QPS
  • 前端笔记-AJAX
  • Excel/WPS表格中图片链接转换成对应的实际图片
  • 大模型应用开发大纲
  • 前端框架开发编译阶段与运行时的核心内容详解Tree Shaking核心实现原理详解
  • C语言中的双链表和单链表详细解释与实现
  • PostgreSQL 用户资源管理
  • 基于LLM的响应式流式处理实践:提升用户体验的关键技术
  • 【python】copy deepcopy 赋值= 对比
  • el-input 限制只能输入非负数字和小数
  • 基于SIMMECHANICS的单自由度磁悬浮隔振器PID控制系统simulink建模与仿真
  • linux基础学习--linux文件与目录管理
  • 【python实用小脚本系列】用Python打造你的专属智能语音助手
  • 【技术派后端篇】技术派中基于 Redis 的缓存实践
  • 快手砍掉本地生活的门槛
  • Redis的使用总结