简介

这章会讲解一些java多线程的基础知识

使用多线程的优点

尽可能发挥多核cpu的作用

线程是大多数操作系统调度的基本单位 (因为一个核上面同时只能执行一个线程,操作系统按照时分的形式 进行调度, 线程会分配到若干时间片,单线程的时间片用完了就会发生调度, 所以说是调度的基本单位)。使用了多线程技术就可以有效使用多个处理器核

更快的响应和更好的编程模型

线程的运行状态

image.png

image.png

理论上当一个线程进入waiting状态, 当被其他线程notify之后会进入到block 状态, 只有拿到wait()函数对应的锁的时候才会 才会从wait()处返回。

守护线程

image.png

启动和终止线程

启动线程一般是parent线程调用线程的start()方法, 告知jvm一旦线程规划器有空闲,就应该立即执行run方法

终止线程的方式

除了等run方法结束,此外还有一些方法可以终止线程。

一般通过中断或者设置一个标识位来进行终止

中断

中断就好比线程的一个标识位属性, 表示一个线程是否被其他线程进行中断过(其他线程调用该线程的interrupt()方法), 线程会检查自己是否被中断来响应(通过调用isInterrupted()方法),也可以调用别的方法进行复位。 当线程处于终结状态时候, 哪怕被中断过,也只会返回false。

线程间的通信

volatile变量 : 保证线程间的可见性 和 有序性, 但是不能保证原子性(拿i ++ 来说明)lock指令, 锁总线 来保证可见性, 有序性通过jvm插入内存屏障

synchorized 保证了可见性和排他性 (进入方法区要获取监视器, 否则会block住, 退出方法区, 会释放锁)

image.png

等待和通知机制

wait 和notify() notifyAll()

image.png

image.png

image.png

有个疑惑的地方,wait依赖于synchronized锁吗 (代码实验好像是的)

两个线程轮流打印

public class TestNotify extends Thread{
private static volatile int a = 0;
public static void main(String[] args) {
Object o = new Object();
AStudent aStudent = new AStudent(o);
AStudent bStudent = new AStudent(o);
Thread astudent = new Thread(aStudent, "Astudent");
Thread bstudent = new Thread(aStudent, "Bstudent");
astudent.start();
bstudent.start();
}
//
static class AStudent implements Runnable{
public Object o;
public AStudent(Object o) {
this.o = o;
}
@SneakyThrows
@Override
public void run() {
while (true) {
synchronized (o) {
o.notify();
System.out.println(Thread.currentThread().getName() + "===========" + ++a);
sleep(1000);
o.wait();
}
}
}
}
}

经典的消费者和生产者范式

等待方:

image.png

消费方:

image.png