1、如何让Java线程安全停止工作
- 自然执行完
- 抛出异常
- 主动停止
2、如何安全地主动停止
stop()、resume()、suspend()这些方法不会释放资源,已经被废弃
java线程是协作式的
interrupt()中断一个线程,并不是强行关闭这线程,而是通知该线程需要关闭,线程收到通知后自动根据实际运行情况才安全关闭。
isinterrupted()判定当前线程是否处于中断状态
注意:如果线程中的方法中会抛出中断异常InterruptedException时,线程的中断标志们会被复位为false,所以在线程外执行interrupt()也会无效,自己在catch中再进行中断
public class EndThread {
private static class UseThread extends Thread {
public UseThread(String name) {
super(name);
}
@Override
public void run() {
String name = Thread.currentThread().getName();
while (!isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("线程出现InterruptedException异常");
System.out.println("抛出异常时interrupt flag is " + isInterrupted());
interrupt(); //需要手动再次中断
}
System.out.println(name + " is running");
}
System.out.println(name + " interrupt flag is " + isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
UseThread linbe = new UseThread("LINBE");
linbe.start();
Thread.sleep(500);
linbe.interrupt(); //线程中断
}
}
3、线程的状态切换
yeild():将线程从运行转到可运行状态(实际上会很少用)
4、深入理解run()和start()方法
调用run()方法相当于调用一个普通方法
public class RunAndStart {
public static class ThreadRun extends Thread {
@Override
public void run() {
int i = 90;
while (i > 0) {
try {
Thread.sleep(1000);
System.out.println("I am " + Thread.currentThread().getName() + " and now the i = " + i--);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ThreadRun beCalled = new ThreadRun();
beCalled.setName("Becalled");
// beCalled.run(); //I am main and now the i =, 运行的是main主程序
beCalled.start(); //I am Becalled and now the i =,调用的才ThreadRun线程
}
}
5、线程间的共享
(1) synchronized内置锁
- 对象锁
- 类锁
(2)volatile关键字
是JVM提供的最轻量的一个锁
(3)ThreadLocal的使用
每个线程独立保存的一个副本,建议用来保存较小的对象
6、等待和通知
6.1 相关方法
wait()对象上的方法
notify()/notifyAll()对象上的方法,使用时尽量使用notifyAll()
6.2 等待和通知的标准范式
等待方:
1)获取对象的锁
2)循环里判断条件是否满足,不满足调用wait方法
3)条件满足执行业务逻辑
通知方:
1)获取对象的锁
2)改变条件
3)通知所有在等待的线程
7、join()方法
线程A执行了B的join()方法后,线程A必须要等待B执行完成了以后,线程A才能继续执行自己的工作
8、调用yield()、sleep()、wait()、notify()等方法对锁的影响
- yield():持有的锁是不释放的
- sleep():持有的锁是不释放的
- wait():调用wait()方法前必须要持有锁,调用了wait()方法后,锁会被释放,当wait()返回的时候,线程会重新持有
- notify():调用notify()方法前必须要持有锁,调用notify()方法本身不释放锁