一个线程启动别的线程
new Thread().start()、 Executor.execute() 等。
一个线程终结另一个线程
Thread.stop()
现在被弃用。它会让线程立即掐断,不管对方在做什么。
Thread.interrupt()
温和式终结,不立即、不强制,只是标记为中断。isInterrupted() 只做中断状态的检查,而 Thread.interrupted() 做检查并重置中断状态(设置为 false)。一般会使用 Thread.interrupted()。如下代码:
1 | public void runTest() { |
一般在耗时事件前面做 Thread.interrupted(),如处理图片之前等。
如下代码:
1 | public void runTest() { |
thread.interrupt() 终止线程时,线程正处于等待(睡眠)状态(代码中主线程等待时间小于子线程等待时间,500<2000),则子线程中抛出 InterruptedException,如果要支持从外部关闭线程,需要在子线程的 catch 方法内操作。如果不处理,则子线程的循环继续执行。InterruptedException 也会重置线程的中断状态。如果在线程等待时中断,或者在中断状态下等待,即先调用“thread.interrupt()”然后再调用“Thread.sleep()”,则直接结束等待过程,因为等待过程什么也不会做,而 interrupt() 的目的是让线程做完收尾工作后尽快终结,所以要跳过等待过程。
如果不打算从外部终结线程,那么 InterruptedException 异常可以不处理。“Thread.sleep()”方法要抛出异常,是为了能在睡眠中被打断。
在 Android 中,有如下方法:
1 | SystemClock.sleep(); |
它和“Thread.sleep()”是一样的,只是它把异常“吞掉”了。
Object.wait() 和 Object.notify() / notifyAll()
如下代码,两个线程,500ms后打印字符串,1000ms后初始化字符串:
1 | public class WaitDemo implements TestDemo { |
输出结果为 null,将 thread1 的睡眠时间修改为2000ms,则可以打印出结果,但现实中耗时的方法可能是无法知道具体执行结束时间的。
使用 Object.wait() 和 Object.notify() / notifyAll() 方法,代码如下:
1 | public class WaitDemo implements TestDemo { |
当线程A访问 printString() 方法时,拿到 Monitor,当它发现 sharedString 为 null 时,执行 wait() 方法,将 Monitor 释放,以便后面的线程可以进入 initString() 执行初始化操作。该线程进入等待队列,等待别的线程唤醒自己,注意此处的队列并不是排队获取 Monitor 的队列。
此处增加排队获取 Monitor 的队列的链接。
当线程B、线程C访问 printString() 方法时,由于 sharedString 为 null 同样进入等待被唤醒的队列。线程D访问 initString() 方法,并且拿到了 Monitor,执行了初始化操作,并执行 notifyAll() 方法,通知之前被等待唤醒的线程A、线程B和线程C。notifyAll() 方法是唤醒所有的等待队列中的线程,而 notify() 只唤醒一个。notifyAll() 方法更常用。
1 | 等待队列中的线程被唤醒后,从 wait() 方法之后,更确切地说是从 catch 异常快结束后的代码开始执行。 |
注意代码中的“while (sharedString == null)”不能修改成“if (sharedString == null)”,wait() 并不能确定是被谁唤醒的,类似 interrupt() 方法不仅可以唤醒 sleep() 也可以唤醒 wait(),抛出 InterruptedException 异常,如果是 if,则代码会继续执行“System.out.println(“String: “ + sharedString);”方法。事实上下面代码块是使用 wait() 非常标准的一种方式:
1 | while (判断条件){ |
wait() 和 notify() / notifyAll() 都需要放在同步代码块(synchronized 修饰的方法或者代码块)里面。
Thread.join()
让另一个线程插在自己前面。如下代码:
1 | ... |
表示 thread2 线程希望 thread1 插队,在对方完全执行结束之后自己再继续之前的执行。
Thread.yield()
暂时让出自己的时间片给同优先级的线程。如下代码:
1 | ... |
参考资料:
腾讯课堂 HenCoder