不推荐使用Thread.stop(), 他会释放所有的monitor, 导致数据不一致.
假设有一条数据库记录, 有两个字段ID, Name.
为了保持同一条记录ID, Name一致, 会在读写该对象的时候加锁.
线程A获取到锁, 开始写操作, 写完ID = 1, 还没写Name, 被强制stop了, 释放掉了锁.
线程B拿到锁, 读取对象, 以为是线程安全的, 实际上数据是错的, 只有ID有值, Name为null.
可以通过调用thread.interrupt()对线程进行中断操作.
当线程收到interrupt信号后, 可能会有两种场景:
线程有两个可以判断是否中断的方法, 如下所示.
使用静态Thread.interrupted, 会清除当前中断状态, 而thread.isInterrupted则不会清除状态.
1 // 中断线程
2 public void Thread.interrupt()
3 // 判断是否被中断
4 public boolean Thread.isInterrupted()
5 // 判断是否被中断,并清除当前中断状态isinterrupt
6 public static boolean Thread.interrupted()
1 public void run() {
2 while (true) {
3 if (Thread.currentThread().isInterrupted()) {
4 System.out.println("Interruted!");
5 break;
6 }
7 Thread.yield();
8 }
9 }
10
11 t1.interrupt();
@Deprecated不推荐使用, 原因是如果在多线程环境中, 假设多个线程调用线程A的suspend和resume.
如果线程B先调用了threadA.suspend(), 线程C再调用threadA.resume(), 则没问题.
如果线程B先调用了threadA.resume(), 线程C再调用threadA.suspend(), 这个时候将导致线程A处于冻结状态, 其持有的锁无法释放.
yield
可以让当前线程暂停一下, 类似于sleep, 但是他不会阻塞该线程, 只是从运行状态切换为就绪状态.
当yeild执行后, 优先级大于等于当前线程优先级的所有线程都会有竞争CPU执行的机会, 他自身也会参与竞争.
join
该操作会使得线程执行存在等待, 如果A线程调用B线程的join操作, 则A会等待B执行完成后, 才会继续往下执行.
线程B执行完毕后, 系统会调用notifyAll()来通知所有等待线程.
join也可以指定时间参数, 等待N秒后, 无论目标线程是否完成, 当前线程都会继续往下执行.
1 //join的本质, 处于等待状态
2 while(isAlive()){
3 wait(0);
4 }
sleep相对容易理解, 他会使得当前Thread进入阻塞状态, 同时不释放该线程占用的锁.
在一个大型系统中, 应当在new Thread的时候给他加上是否为守护线程, 以及线程名称.
防止系统退出的时候, 出现一堆Thread未关闭阻塞退出.
1 Thread t= new DaemonT();
2 t.setName("DaemonT");
3 t.setDaemon(true);
4 t.start();
高优先级的线程更容易在竞争中获胜, 但并不是绝对的.
1 Thread high=new HightPriority();
2 LowPriority low=new LowPriority();
3 high.setPriority(Thread.MAX_PRIORITY);
4 low.setPriority(Thread.MIN_PRIORITY);
5 low.start();
6 high.start();
synchronized
Object.wait 和 Object.notify notifyAll
三个方法都是Object对象的方法, 需要在synchronized语句块内使用.
wait
使当前线程暂停执行并释放对象锁标示, 让其他线程可以进入synchronized数据块, 当前线程被放入对象等待池中
notify
从对象的等待池中移走一个任意的线程并放到锁标志等待池中, 只有锁标志等待池中线程能够获取锁标志;
如果锁标志等待池中没有线程,则notify()不起作用
notifyAll
从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中
1 public class SimpleWait {
2
3 private static final Object lock = new Object();
4
5 private static class T1 extends Thread {
6
7 @Override
8 public void run() {
9 synchronized (lock) {
10 System.out.println("T1 start!");
11
12 try {
13 System.out.println("T1 wait for lock!");
14 lock.wait();
15 } catch (InterruptedException e) {
16 e.printStackTrace();
17 }
18 // 2s后, T2释放锁, T1拿到锁才开始执行wait后的操作
19 System.out.println("T1 end!");
20 }
21 }
22 }
23 private static class T2 extends Thread {
24
25 @Override
26 public void run() {
27 synchronized (lock) {
28 System.out.println("T2 start, notify others!");
29 lock.notify();
30 System.out.println("T2 end!");
31 try {
32 Thread.sleep(2000);
33 } catch (InterruptedException e) {
34 e.printStackTrace();
35 }
36 }
37 }
38 }
39
40 public static void main(String[] args){
41 T1 t1 = new T1();
42 T2 t2 = new T2();
43 t1.start();
44 t2.start();
45 }
46 }
下一篇博文我们将讲述Java内存模型