【无标题】

 Thread 的几个常见属性

属性 获取方法
ID getId()
名称 getName()
状态 getState()
优先级 getPriority()
是否是后台线程 isDaemon()
是否存活 isAlive()
是否被中断

isInterrupted()

  • ID 是线程的唯一标识,不同线程不会重复
  • 名称是各种调试工具用到
  • 状态表示线程当前所处的一个情况,下面我们会进一步说明
  • 优先级高的线程理论上来说更容易被调度到
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
  • 是否存活,即简单的理解,为 run 方法是否运行结束了
  • 线程的中断问题,下面我们进一步说明
public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
try {
System.out.println(Thread.currentThread().getName() + ": 我还
活着");
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
                    e.printStackTrace();
               }
           }
            System.out.println(Thread.currentThread().getName() + ": 我即将死去");
       });
        System.out.println(Thread.currentThread().getName() 
                           + ": ID: " + thread.getId());
        System.out.println(Thread.currentThread().getName() 
                           + ": 名称: " + thread.getName());
        System.out.println(Thread.currentThread().getName() 
                           + ": 状态: " + thread.getState());
        System.out.println(Thread.currentThread().getName() 
                           + ": 优先级: " + thread.getPriority());
        System.out.println(Thread.currentThread().getName() 
                           + ": 后台线程: " + thread.isDaemon());
        System.out.println(Thread.currentThread().getName() 
                           + ": 活着: " + thread.isAlive());
        System.out.println(Thread.currentThread().getName() 
                           + ": 被中断: " + thread.isInterrupted());
        thread.start();
        while (thread.isAlive()) {}
        System.out.println(Thread.currentThread().getName() 
                           + ": 状态: " + thread.getState());
   }
}


 启动一个线程-start()

之前我们已经看到了如何通过覆写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程 就开始运行了。
调用 start 方法 , 才真的在操作系统的底层创建出一个线程 .
 
 

中断一个线程

目前常见的有以下两种方式:
1. 通过共享的标记来进行沟通
2. 调用 interrupt() 方法来通知
 
示例 -1: 使用自定义的变量来作为标志位
 
需要给标志位上加 volatile 关键字
示例 -2: 使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定
义标志位.
Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记.
 
【无标题】_第1张图片

使用 thread 对象的 interrupted() 方法通知线程结束.

thread 收到通知的方式有两种:
1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通
知, 清除中断标志
当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择
忽略这个异常, 也可以跳出循环结束线程.
2. 否则,只是内部的一个中断标志被设置,thread 可以通过
Thread.interrupted() 判断当前线程的中断标志被设置, 清除中断标志
Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置, 不清除中断标志
这种方式通知收到的更及时,即使线程正在 sleep 也可以马上收到
 
示例 -3 观察标志位是否清除
标志位是否清除, 就类似于一个开关.
Thread.isInterrupted() 相当于按下开关, 开关自动弹起来了. 这个称为 "清除标志位"
Thread.currentThread().isInterrupted() 相当于按下开关之后, 开关弹不起来, 这个称为
"不清除标志位".
使用 Thread.isInterrupted() , 线程中断会清除标志位
使用 Thread.currentThread().isInterrupted() , 线程中断标记位不会清除.

一个线程-join()

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        Runnable target = () -> {
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() 
                                       + ": 我还在工作!");
                    Thread.sleep(1000);
               } catch (InterruptedException e) {
                    e.printStackTrace();
               }
           }
            System.out.println(Thread.currentThread().getName() + ": 我结束了!");
       };
        Thread thread1 = new Thread(target, "李四");
        Thread thread2 = new Thread(target, "王五");
        System.out.println("先让李四开始工作");
        thread1.start();
        thread1.join();
        System.out.println("李四工作结束了,让王五开始工作");
        thread2.start();
        thread2.join();
        System.out.println("王五工作结束了");
   }
}
方法 说明
public void join()
等待线程结束
public void join(long millis)
等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos)
同理,但可以更高精度

获取当前线程引用

方法 说明
public static Thread currentThread();
返回当前线程对象的引用
public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
   }
}

休眠当前线程

也是我们比较熟悉一组方法,有一点要记得,因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的
 
方法 说明
public static void sleep(long millis) throws InterruptedException
休眠当前线程 millis 毫秒
public static void sleep(long millis, int nanos) throws
InterruptedException
可以更高精度的休眠
public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(3 * 1000);
        System.out.println(System.currentTimeMillis());
   }
}

 

 

你可能感兴趣的:(java,开发语言)