Thread类和Runnable 接口

  • 获取和设置Thread对象信息的方法。
    • getId():该方法返回Thread对象的标识符。该标识符是在钱程创建时分配的一个正 整数。在线程的整个生命周期中是唯一且无法改变的。
    • getName()/setName():这两种方法允许你获取或设置Thread对象的名称。这个名 称是一个String对象,也可以在Thread类的构造函数中建立。
    • getPriority()/setPriority():你可以使用这两种方法来获取或设置Thread对象的优先 级。
    • isDaemon()/setDaemon():这两种方法允许你获取或建立Thread对象的守护条件。
    • getState():该方法返回Thread对象的状态。
  • sleep(long ms):该方法将线程的执行暂停ms时间。
  • join():暂停线程的执行,直到调用该方法的线程执行结束为止。可以使用该方法等待另一个 Thread对象结束。
  • setUncaughtExceptionHandler():当线程执行出现未校验异常时,该方法用于建立未校验异 常的控制器。
  • currentThread():Thread类的静态方法,返回实际执行该代码的Thread对象。

    中断

  1. interrupt():中断目标线程,给目标线程发送一个中断信号,线程被打上中断标记。
  2. interrupted():判断目标线程是否被中断,但是将清除线程的中断标记。(静态方法
  3. isinterrupted():判断目标线程是否被中断,不会清除中断标记

    thread.isInterrupted()与Thread.interrupted()的区别

    因为 thread.interrupted()相当于给线程发送了一个唤醒的信号,所以如果线程此时恰好处于 WAITING或者TIMEDWAITING状态,就会抛出一个InterruptedException,并且线程被唤醒。而如果 线程此时并没有被阻塞,则线程什么都不会做。**但在后续,线程可以判断自己是否收到过其他线程发来 的中断信号,然后做一些对应的处理(aqs 和 condition中用到这个特性了)_**

    这两个方法都是线程用来判断自己是否收到过中断信号的,前者是实例方法,后者是静态方法。二 者的区别在于,前者只是读取中断状态,不修改状态;后者不仅读取中断状态,还会重置中断标志位。

  1. public static void main(String[] args) throws InterruptedException{
  2. Thread thread = new Thread(new Runnable() {
  3. @Override
  4. public void run() {
  5. while (true) {
  6. }
  7. }
  8. });
  9. thread.start();
  10. // 设置中断位
  11. thread.interrupt();
  12. System.out.println("isInterrupted: " + thread.isInterrupted());
  13. // 虽然调用者是thread 但实际上 static修饰的 获取的是主线程的中断状态
  14. System.out.println("isInterrupted: " + thread.interrupted());
  15. System.out.println("isInterrupted: " + Thread.interrupted());
  16. System.out.println("isInterrupted: " + thread.isInterrupted());
  17. thread.join();
  18. System.out.println("main is over");
  19. }

image.png

  1. public static void main(String[] args) throws InterruptedException{
  2. Thread thread = new Thread(new Runnable() {
  3. @Override
  4. public void run() {
  5. while (!Thread.currentThread().interrupted()) {
  6. }
  7. System.out.println("thread isInterrupted:" + Thread.currentThread().isInterrupted());
  8. }
  9. });
  10. thread.start();
  11. // 设置中断位
  12. thread.interrupt();
  13. thread.join();
  14. System.out.println("main is over");
  15. }

image.png

优雅的关闭线程

设置标志位

  1. public class CloseThreadElegant {
  2. public static void main(String[] args) throws InterruptedException {
  3. MyThread myThread = new MyThread();
  4. myThread.start();
  5. Thread.sleep(5000);
  6. myThread.stopRunning();
  7. myThread.join();
  8. }
  9. }
  10. class MyThread extends Thread {
  11. private boolean running = true;
  12. @Override
  13. public void run() {
  14. while (running) {
  15. System.out.println("线程正在运行。。。");
  16. try {
  17. Thread.sleep(1000);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }
  23. public void stopRunning() {
  24. this.running = false;
  25. }
  26. }

但上面的代码有一个问题:如果MyThread t在while循环中阻塞在某个地方,例如里面调用了
object.wait()函数,那它可能永远没有机会再执行 while( ! stopped)代码,也就一直无法退出循环。

此时,就要用到InterruptedException()与interrupt()函数。