多线程就是在实施某一程序的空闲时间内去实施另一程序,可以提高运行效率

并行和并发

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

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

实现方法

继承Thread类的

  • 定义一个类继承Thread

  • 重写run方法

1
2
3
4
5
6
7
8
public class MyThread extends java.lang.Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("日奈");
}
}
}
  • 创建子类的对象,并启动线程
1
2
MyThread t = new MyThread();
t.start();

用start就是启动线程,而用run的话就是单纯的调用方法

实现Runnable接口

  • 定义一个类继承Runnable
  • 重写run方法
1
2
3
4
5
6
7
public class MyRun implements java.lang.Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("日奈");
}
}

}

  • 创建自己类的对象
  • 创建Thread类的对象,并开启线
1
2
3
MyRun r = new MyRun();
Thread t = new Thread(r);
t.start();

利用Callable接口和Future接口

  • 创建自己类(如MyCallable)实现Callable接口
  • 重写call(有返回值)
1
2
3
4
5
6
7
8
9
10
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int p = 0;
for (int i = 1; i <= 100; i++) {
p += i;
}
return p;
}
}
  • 创建MyCallable的对象(表示多线程要执行的任务)
1
MyCallable mc = new MyCallable();
  • 创建FutureTask的对象(管理多线程运行的结果)
1
FutureTask<Integer> ft = new FutureTask<>(mc);
  • 创建Thread类的对象,并启动
1
2
Thread t = new Thread(ft);
t.start();
  • 获取多线程运行的结果
1
2
Integer i = ft.get();
System.out.println(i);

常见成员方法

image-20250918201328275

优先级:最低为1,最高为10

守护线程:就相当于备胎

当非守护线程执行完毕后,守护线程会执行一段时间,在结束(不会执行所有)

线程的生命周期

image-20250918205040016

同步代码块&同步方法

当有多个线程启动的时候,会发生一系列错误

如:a线程运行的时候,还没运行完成,这时b线程抢夺了a线程的位置而实行b线程,导致结果出问题

这时候就要在a线程运行的时候把线程锁住 而不让其他的线程插入进来

同步代码块

synchronized (锁) {

​ 操作共享数据的代码

}

其中“锁”要是唯一的,所以定义时要用static

如:static Object oj = new Object();

特点

  • 锁默认打开,有一个线程进去了,锁自动关闭
  • 里面的代码全部执行完毕,线程出来,锁自动打开

同步方法

就可以看作把同步代码块中synchronized提取出来

格式

修饰符 synchronized 返回值类型 命名 (参数){…}

特点

  • 同步方法是锁住方法里面所有的代码
  • 锁对象不能自己指定: 非静态 this 静态 当前类的字节码文件对象(文件名.class)

等待唤醒机制

image-20250919192114492

阻塞队列

image-20250919194427149

线程池

按照之前的多线程的方法,都是用完就扔了,既浪费资源又浪费时间,因此通过线程池把线程存储起来

原理

image-20250920204838315

image-20250920205042186

提交任务:对象.submit()

销毁线程池:对象.shutdown()

自定义线程池

image-20250920210214496

当核心线程和队伍都满的时候,临时线程才会处理剩下的线程78,并不会先处理456

image-20250920210508911

如果有是个线程,多出来的任务10会触发任务拒绝策略

image-20250920210854361