Thread 线程
1. 重要的知识概念
1.1 锁池
假设线程A已经拥有了某个对象(不是类)的锁,而其它线程B、c想要调用这个对象的某个synchronized方法(或者块),由于B、c线程在进入对象的synchronized方法(或者块)之前必须先获得该对象锁的拥有权,而恰巧该对象的锁目前正被线程A所占用,此时B、c线程就会被阻塞,进入一个地方去等待锁的释放,这个地方便是该对象的锁池
1.2 等待池(等待队列)
假设线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁,同时线程A就进入到了该对象的等待池中,进入到等待池中的线程不会去竞争该对象的锁。
通过等待池和锁池概念的理解,就可以理解notify和notifyAll的区别
notifyAll会让所有处于等待池的线程全部进入锁池去竞争获取锁的机会
notify只会随机选取一个处于等待池中的线程进入锁池去竞争获取锁的机会。
无论哪一个最终仍然只有一个线程获得锁,不同的是notify方法会唤醒一个等待池中的一个线程,notifyAll方法唤醒会所有线程(未获得锁的线程进入锁池)
可以说两个池中的线程都是处于阻塞状态,但是阻塞的原因是不同的(或者根据下面线程的状态分为等待状态和阻塞状态)
1.3 线程的状态
//Thread内部枚举类
public enum State {
//创建后尚未启动的线程的状态
NEW,
//包含Running和Ready
RUNNABLE,
/** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */
//等待获取排他锁,比如 synchronized block 进入锁池
BLOCKED,
//无限期等待 Object#wait()、join() 、LockSupport#park() 进入等待池
WAITING,
/** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */
//限期等待
TIMED_WAITING,
//终止结束
TERMINATED;
}
2. 重要的方法
2.1 start()
线程启动方法
2.2 join()
2.3 yield()
- 当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示。
- 不会对锁产生影响
2.4 sleep(long time)
sleep()只会让出CPU,线程进入有限期的等待状态(阻塞状态)
但是sleep方法不会影响已经获得的锁,这是与Object对象的wait方法的根本区别
2.5 interrupt()
线程打断方法,但是存在两种情况
- 如果线程处于被阻塞状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。
- 如果线程处于正常活动状态,那么会将该线程的中断标志设置为true。被设置中断标志的线程将继续正常运行,不受影响。
建议:需要被调用的线程配合中断,在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。
demo
public class ThreadInterruptDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName()+" 开始运行");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+" 执行完成");
} catch (InterruptedException e) {
System.out.println("抛出中断异常");
}
},"ThreadA");
thread.start();
Thread.sleep(500);
thread.interrupt();
}
/** 输出: ThreadA 开始运行 抛出中断异常 */
}
public class ThreadInterruptDemo2 {
private static volatile boolean t = false;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName()+" 开始运行");
while (!t) {
System.out.println(Thread.currentThread().getName()+" 正在运行");
}
System.out.println(Thread.currentThread().getName()+" 执行完成");
},"ThreadA");
thread.start();
Thread.sleep(10);
thread.interrupt();
t =true;
}
}
/** 输出: ThreadA 开始运行 ThreadA 正在运行 ThreadA 正在运行 ThreadA 正在运行 ..... ThreadA 正在运行 ThreadA 执行完成 **/