一、sleep() 与 wait()
两者都会让当前线程进入等待状态。唤醒后都需要等待 CPU 资源,不一定会立即执行。若在等待期间被调用此线程的的 interrupt() 方法,将会产生 InterruptedException 异常。
wait() 是 Object 类的方法,会释放对象锁,并让出 CPU 资源。只能在 synchronized 下使用,使用 notify() 或 notiftAll() 唤醒。
//线程工厂,这里主要用来设置线程名字
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();//创建线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6, 6, 0L,
TimeUnit.MILLISECONDS,new LinkedBlockingQueue(1024),
namedThreadFactory,newThreadPoolExecutor.AbortPolicy());
Object object= newObject();
threadPool.execute(()->{try{synchronized(object) {
object.wait();
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAA");
}
}catch(InterruptedException e) {
e.printStackTrace();
}
});
threadPool.execute(()->{synchronized(object) {
System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBBBB");
object.notify();
}
});
View Code
sleep() 是 Thread 类的静态方法,只会让出 CPU 资源。可以使低优先级的线程得到执行的机会。
//线程工厂,这里主要用来设置线程名字
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();//创建线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6, 6, 0L,
TimeUnit.MILLISECONDS,new LinkedBlockingQueue(1024),
namedThreadFactory,newThreadPoolExecutor.AbortPolicy());
threadPool.execute(()->{try{//阻塞 1 秒
Thread.sleep(1000);
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}catch(InterruptedException e) {
e.printStackTrace();
}
});
threadPool.execute(()->{
System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBBBBB");
});
View Code
两个示例都保证了 B 会在 A 之前被打印
二、notify() 与 notifyAll()
与 wait() 配合使用。两者都会唤醒其他线程,且会释放对象锁,不会阻塞当前线程。
其中 notify() 只唤醒等待线程当中的一个,notifyAll() 会唤醒所有等待线程。
notify() 是随机唤醒的,不同的 JDK 版本,在等待队列中唤醒的线程,其位置在等待队列中不同。
JDK1.8 中 notify() 唤醒的是等待队列中的头节点,即等待时间最长的那个线程。
唤醒的线程为同一个对象锁的线程。唤醒一个或所有,都只有一个线程会获取到锁对象。
三、yield() 与 join()
yield() 是 Thread 类的静态原生 (native) 方法,作用是让出 CPU 资源,不会阻塞当前线程,但可能让出 CPU 资源后,系统重新调度后又会选择给该线程 CPU 资源。使用场景比较少。
join() 是 Thread 类实例的方法,可以使得一个线程在另一个线程结束后再执行。当前运行的线程将进入到等待状态直到另一个线程执行完成。
Thread t1 = newThread(){
@Overridepublic voidrun() {try{
Thread.sleep(1000);
System.out.println("A");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2= newThread(){
@Overridepublic voidrun() {try{
t1.join();
System.out.println("B");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
};
t2.start();
t1.start();
View Code
示例中保证了 A 在 B 之前被打印
四、interrupt()
中断等待状态的线程,并抛出异常。相关方法有三个。
interrupt() 是 Thread 类实例的方法,给线程中断状态设置为 false,等线程进入到等待状态时就会被中断,并抛出异常
isInterrupted() 是 Thread 类实例的方法,检测线程的中断状态
interrupted() 是 Thread 类的静态方法,实质调用的是 currentThread().isInterrupted(true),作用是检测线程的中断状态,然后将状态设置为 true
Thread t1 = newThread() {
@Overridepublic voidrun() {try{
System.out.println(Thread.currentThread().getName()+ "启动后的中断状态:" +Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().getName()+ "interrupt()后的中断状态:" +Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread().getName()+ "isInterrupted()获取中断状态:" +Thread.interrupted());
System.out.println(Thread.currentThread().getName()+ "interrupted()后的中断状态:" +Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName()+ "异常时中断状态:" +Thread.interrupted());
}
}
};newThread() {
@Overridepublic voidrun() {
System.out.println(t1.getName()+ "未启动时的中断状态:" +t1.isInterrupted());
System.out.println("=======================================================");
t1.start();try{
t1.join();
System.out.println("=======================================================");
System.out.println(t1.getName()+ "执行完时的中断状态:" +t1.isInterrupted());
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}.start();
View Code