Author:老九
计算机专业
可控之事 沉重冷静 不可控之事 乐观面对
85180586@qq.com
☺️
❓ ❤️ ☕️ ❗️
————————————————
版权声明:本文为CSDN博主「浦上青天」的原创文章
第五天 第六天复习
线程安全问题阻塞队列定时器
定时器构成
构造方法快捷键 线程池
核心操作 线程总结
知识点 第五天 第六天复习
线程安全问题单例模式:某个类,不应该有多个实例,此时就可以使用单例模式
实现方式:1.懒汉模式2.饿汉模式
饿汉模式:在类加载的时候立刻实例化对象(实例化时机早)
懒汉模式:首次调用getInstance的时候再实例化对象(效率更高)
阻塞队列1.饿汉模式,是线程安全的,多线程调用getInstance只涉及读操作
2.懒汉模式,在实例化对象之前是线程不安全的(涉及到多线程修改),一旦实例化之后,又是线程安全的
懒汉模式改进方式:
1.加锁(读取判断和new实例操作是原子的)
2.双重if(避免在实例化之后,再去调用getInstance频繁触发不必要的加锁操作)
3.volatile(在instance实例之前加)
可以用来实现生产者消费者模型
阻塞队列是一个先进先出的队列
出队列的时候,如果发现队列空了,也会阻塞,直到有其他线程调用入队列操作,让队列中有元素,才能继续出队列
入队列的时候如果发现队列满了,就会阻塞,直到有其他线程调用出队列操作让队列中有空位的时候,才能继续入队列
public class ThreadDemo24 { static class BlockingQueue { private int[] array = new int[1000]; private int head = 0; private int tail = 0; //head 和 tail 构成一个前闭后开区间 //区分空还是满 private int size = 0; //阻塞版本入队列 public void put(int value) throws InterruptedException { synchronized (this) { if (size == array.length) { wait(); } array[tail] = value; tail++; if (tail == array.length) { tail = 0; } size++; notify(); } } public int take() throws InterruptedException { int ret = -1; synchronized (this) { if (size == 0) { wait(); } ret = array[head]; head++; if (head == array.length) { head = 0; } size--; notify(); } return ret; } }}
定时器这两个wait不可能同时被调用
定时器构成多线程编程中一个重要/常用组件
好比一个闹钟,有些逻辑,并不想立刻执行,而是等一定的时间之后,再来执行
例如,用户服务器,浏览器内部,淘宝服务器都有定时器,就跟闹钟是一样的,如果定时器时间到了,就不等了
1.使用一个类Task来描述“一段逻辑”(一个要执行的任务),同时也要记录这个任务在啥时候执行
阻塞优先队列:既支持阻塞的特性,又支持按优先级“先进先出”
本质上是一个“堆”
2.使用一个阻塞优先队列来组织若干个Task
3.还需要一个扫描线程,扫描线程要循环的检测队首元素需要执行,如果需要执行的话,就执行这个任务
java.util.concurrent 简称juc,包含很多并发编程的包
wait()死等,一直等到notify的通知过来
wait(time),等待是有上限,如果有notify就被提前唤醒,或者跟sleep一样
import javafx.concurrent.Worker;import java.sql.Time;import java.util.concurrent.PriorityBlockingQueue;public class ThreadDemo25 { //优先队列中的元素必须是可比较的 //1.让Task 实现Comparable接口 //2.让优先队列构造的时候,传入一个比较器对象(Comparator) static class Task implements Comparable
ALT+INSERT
线程池核心操作已经包含了一些线程,让我们直接去使用
避免了频繁创建/销毁线程的开销
execute:把一个任务加到线程池中
shutdown:销毁线程池中的所有线程
线程池的组成部分
1.先有一个类,表示 工作线程
2.还得有一个类,来描述具体线程要做的工作是啥(借助runnable就可以表示
3.还需要有一个数据结构来组织若干个任务,BlockingQueue)
4.还需要一个数据结构,来组织若干个线程List
import java.util.ArrayList;import java.util.List;import java.util.concurrent.BlockingQueue;import java.util.concurrent.linkedBlockingQueue;public class ThreadDemo26 { //使用这个类来描述当前的工作线程是啥样的 static class Worker extends Thread { private int id = 0; private BlockingQueue
1.进程和线程的基本概念和区别
2.线程控制
a线程创建
b线程终止
c线程等待
d获取线程实例
e线程休眠
3.线程状态
4.线程安全【重中之重】
基本概念:多线程执行某个逻辑出现了逻辑错误
出现的原因:
1.抢占式执行(万恶之源)
2.修改操作不是原子的
3.多线程修改同一个变量
4.内存可见性(volatile,一个线程读,一个线程写,其中读操作被优化成直接取CPU寄存器数据,当写线程进行修改的时候,读线程无法获取到最新的值)
5.指令重排序
解决方案:
最主要的方案:
加锁(原子性)
对象等待集(避免出现线程饿死问题)
wait本质上就是当前线程对应的PCB移动到阻塞队列中,直到notify唤醒的时候再把PCB移动回来
wait内部做了三件事:
1.释放锁
2.等待通知
3.收到通知后尝试重新获取锁
先赞后看,养成习惯!!!^ _ ^♥♥♥
每天都更新知识点哦!!!
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘记关注我哦!