new commit

This commit is contained in:
icecat
2026-01-07 16:14:38 +08:00
parent e2d599debe
commit ccf7b50b0d
137 changed files with 1771 additions and 0 deletions

467
线程.md Normal file
View File

@@ -0,0 +1,467 @@
# 线程
## 进程和线程
### 进程介绍:
![image-20251226164954480](https://gitee.com/icecat2233/picture/raw/master/20251226164956071.png)
<img src="https://gitee.com/icecat2233/picture/raw/master/20251226170135578.png" alt="image-20251226170130636" style="zoom:50%;" />
### 线程Thread介绍
进程可以同时执行多个任务,每个任务就是线程:
### 多线程的作用:
提升执行效率,使更多进程可以并行执行
服务器必须用多线程
## Java中开启线程的方式
### 1:继承Thread类
案例:
```Java
public static void main(String[] args) {
/*
* 继承Thread类
* 重写run方法
* 将线程任务代码写在run方法
* 创建对象
* 对象名.start开启线程
* 只有调用start方法才会开启一个新线程
*/
Demo d1 = new Demo();
Demo d2 = new Demo();
d1.start();
d2.start();
}
}
class Demo extends Thread {
@Override
public void run() {
for (int i = 1; i <= 200; i++) {
System.out.println("打印了" + i);
}
}
}
```
### 注意:
![image-20251226175706557](https://gitee.com/icecat2233/picture/raw/master/20251226175707664.png)
### 2实现Runnable接口
```java
/*
方法2 实现runnable接口
编写一个类实现接口
重写run方法
创建线程任务资源(就是创建对象)
然后创建线程对象,将任务资源传入,走构造方法
使用线程对象调用start方法
*/
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread tr = new Thread(mr);
tr.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("八奈见杏菜");
}
}
```
### 3实现Callable接口(有结果返回)
```java
public class ThreadDemo3 {
public static void main(String[] args) throws Exception {
/*
创建一个类实现Callable接口
重写call方法
创建线程任务资源对象
创建线程任务对象封装线程任务资源FutureTask
创建线程对象传入线程任务
使用线程对象调用start方法开启线程
*/
MyCallAble mc = new MyCallAble();
FutureTask<Integer> ft = new FutureTask<>(mc);
Thread t = new Thread(ft);
t.start();
Integer result = ft.get();
System.out.println(result);
}
}
class MyCallAble implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
```
### 尽量选择后两个,拓展性更好
## 线程的方法
![image-20251226195404148](https://gitee.com/icecat2233/picture/raw/master/20251226195406047.png)
### 名字相关:
![image-20251226195311173](https://gitee.com/icecat2233/picture/raw/master/20251226195312281.png)
### 休眠线程:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251226195658228.png" alt="image-20251226195657226" style="zoom: 67%;" />
### 线程调度方法:
Java是抢占式调度
<img src="https://gitee.com/icecat2233/picture/raw/master/20251226200312037.png" alt="image-20251226200310813" style="zoom:67%;" />
### 守护线程
`final void setDaemon(boolean on );`
<img src="https://gitee.com/icecat2233/picture/raw/master/20251226200638217.png" alt="image-20251226200636908" style="zoom: 67%;" />
如图代码所示t2守护t1t1线程任务结束t2也结束(不是立刻结束t2会在苟活一会儿)
哪个线程对象调用setDaemon方法这个线程就是守护线程
## 线程的安全与同步
<img src="https://gitee.com/icecat2233/picture/raw/master/20251227180107783.png" alt="image-20251227180059497" style="zoom: 50%;" />
### 1.同步代码块:
![image-20251227181232243](https://gitee.com/icecat2233/picture/raw/master/20251227181233315.png)
**使用同步代码块指定锁对象时,用类的字节码对象**
**共享数据要用static修饰**
### 2.同步方法:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251227182958488.png" alt="image-20251227182957021" style="zoom: 67%;" />
### 3.Lock锁
```Java
public static void main(String[] args) {
TicketShop1 ts = new TicketShop1();
Thread t1 = new Thread(ts);
Thread t2 = new Thread(ts);
Thread t3 = new Thread(ts);
t1.start();
t2.start();
t3.start();
}
}
class TicketShop1 implements Runnable{
private int ticket = 100;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
//上锁
try {
lock.lock();
if (ticket == 0){
break;
}
System.out.println("卖出了"+ticket+"号票");
ticket--;
} finally {
//记得关闭锁
lock.unlock();
}
}
}
}
```
附加知识点:死锁:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251227184708459.png" alt="image-20251227184706346" style="zoom:50%;" />
## 线程通信
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228190237885.png" alt="image-20251228190234137" style="zoom:50%;" />
### 两条线程交替执行案例:
```Java
public static void main(String[] args) {
Print p = new Print();
Thread t1= new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (Print.class) {
try {
p.print1();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (Print.class) {
try {
p.print2();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});
t2.start();
}
}
class Print{
private int flag = 1;
public void print1() throws InterruptedException {
if (flag != 1){
//wait只能通过锁对象进行调用
Print.class.wait();
}
System.out.print("");
System.out.print("");
System.out.print("");
System.out.print("");
System.out.print("");
System.out.println();
flag = 2;
//notif拥有空唤醒的权利
Print.class.notify();
}
public void print2() throws InterruptedException {
if (flag != 2){
Print.class.wait();
}
System.out.print("");
System.out.print("");
System.out.print("");
System.out.print("");
System.out.println();
flag = 1;
Print.class.notify();
}
}
```
### 注意事项:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228190306178.png" alt="image-20251228190304630" style="zoom: 67%;" />
### 若想提升效率使用ReentrantLock实现同步获取Condition对象
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228191731287.png" alt="image-20251228191729896" style="zoom:50%;" />
注意:第一次指定线程等待时,绑定了线程
### 三条线程交替执行案例:
```Java
public static void main(String[] args) {
Printer p = new Printer();
Thread t1= new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print1();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print2();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t2.start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
p.print3();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
}
}
class Printer{
private int flag = 1;
ReentrantLock lock = new ReentrantLock();
//调用newCondition来获取条件对象以此来指定线程
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
public void print1() throws InterruptedException {
lock.lock();
if (flag != 1){
//第一次调用await方法时绑定了线程
c1.await();
}
System.out.print("");
System.out.print("");
System.out.print("");
System.out.print("");
System.out.print("");
System.out.println();
flag = 2;
c2.signal();
lock.unlock();
}
public void print2() throws InterruptedException {
lock.lock();
if (flag != 2){
c2.await();
}
System.out.print("");
System.out.print("");
System.out.print("");
System.out.print("");
System.out.println();
flag = 3;
c3.signal();
lock.unlock();
}
public void print3() throws InterruptedException {
lock.lock();
if (flag != 3){
c3.await();
}
System.out.print("");
System.out.print("");
System.out.print("");
System.out.print("");
System.out.println();
flag = 1;
c1.signal();
lock.unlock();
}
}
```
### 生产者消费者模式:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228193331390.png" alt="image-20251228193330122" style="zoom:50%;" />
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228193430647.png" alt="image-20251228193429569" style="zoom:50%;" />
### 生产者消费者案例:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228193309975.png" alt="image-20251228193308023" style="zoom:67%;" />
## 线程生命周期:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228194047345.png" alt="image-20251228194046082" style="zoom:67%;" />
## 线程池:
重点:自定义线程池
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228200136901.png" alt="image-20251228200135970" style="zoom:50%;" />
**拒绝策略**用的最多的只有第一种AbortPolicy
![image-20251228200427425](https://gitee.com/icecat2233/picture/raw/master/20251228200428737.png)
**任务队列:**
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228200930260.png" alt="image-20251228200929336" style="zoom: 80%;" />
### 总结:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228200821304.png" alt="image-20251228200820075" style="zoom:50%;" />
### 案例:
```Java
public class Demo3 {
public static void main(String[] args) {
ThreadPoolExecutor tp = new ThreadPoolExecutor(
3,//核心数
6,//最大核心数
10,//空闲时间
TimeUnit.SECONDS,//时间单位
new ArrayBlockingQueue<>(10),//排队人数
Executors.defaultThreadFactory(),//线程对象任务工厂,基本为固定
new ThreadPoolExecutor.AbortPolicy()//拒绝策略,基本只用这个方法
);
for (int i = 1; i <17 ; i++) {
tp.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "调用了hhh");
}
});
}
tp.shutdown();
}
}
```
## 单例设计模式:
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228204751280.png" alt="image-20251228204750037" style="zoom:50%;" />
两种方式:
**饿汉式:简单不烧脑**
直接创建出对象 而不是调用方法的时候再创建对象
**懒汉式:(延迟加载模式):**
<img src="https://gitee.com/icecat2233/picture/raw/master/20251228204928022.png" alt="image-20251228204926855" style="zoom:50%;" />