Thread类及常见方法

目录

1.Thread类概念

2.Thread的常见构造方法

3.Thread的几个常见属性

4.启动一个线程—start( )

5.中断一个线程

1.使用自定义的变量来作为标志位

 2.使用interrupt()

3.观察标志位是否被清除

6.等待一个线程-join()

7.获取当前线程引用

8.休眠当前线程


1.Thread类概念

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。

每个执行流,也需要有一个对象来描述,类似下图所示,而 Thread 类的对象 就是用来描述一个线程执行流的,  JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

2.Thread的常见构造方法

方法

说明

Thread()

创建线程对象

Thread(Runnable target)

使用 Runnable 对象创建线程对象

Thread(String name)

创建线程对象,并命名

Thread(Runnable target, String name)

使用 Runnable 对象创建线程对象,并命名

Thread(ThreadGroup group, Runnable target)

线程可被用来分组管理,分好的组为线程组,

Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");

3.Thread的几个常见属性

属性

获取方法

    ID

getId()

名称

getName()

状态

getState()

优先级

getPriority()

是否后台线程

isDaemon()

是否存活

isAlive()

是否被中断

isInterrupted()

注意:

ID 是线程的唯一标识,不同线程不会重复

名称是各种调试工具用到

状态表示线程当前所处的一个情况,之后我会进一步说明

关于后台线程,需要记住一点: JVM会在一个进程的所有非后台线程结束后,才会结束运行。

是否存活,即简单的理解,为 run 方法是否运行结束

线程的中断问题,下面我们进一步说明

4.启动一个线程—start( )

之前我们已经看到了如何通过覆写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。

覆写 run 方法是提供给线程要做的事情的指令清单

创建线程对象就可以认为是把张三、李四喊过来了

而调用start()方法则就是喊一声,行动起来!现成才去真正独立的执行了

5.中断一个线程

李四一旦进到工作状态,他就会按照行动指南上的步骤去进行工作,不完成是不会结束的。但有时我们需要增加一些机制,例如老板突然来电话了,说转账的对方是个骗子,需要赶紧停止转账,那张三该如 何通知李四停止呢?这就涉及到我们的停止线程的方式了。

目前常见的有以下两种方式:

1.使用自定义的变量来作为标志位

需要给标志位上加 volatile 关键字(保证内存可见性

public class InterruptTest {
    public static volatile boolean isQuit = false;

    static class RunnableT implements Runnable {
        @Override
        public void run() {
            while (!isQuit) {
                System.out.println(Thread.currentThread().getName()
                        + "张三正在操作转账!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            System.out.println("及时中断转账!");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        RunnableT runnableT = new RunnableT();
        Thread thread = new Thread(runnableT);
        thread.start();
        Thread.sleep(3000);
        System.out.println("老板来电话,得知对面是骗子!");
        isQuit = true;


    }
}

运行结果:

 2.使用interrupt()

Thread内部包含了一个boolean类型的变量作为线程是否被中断的标记

方法

说明

public void interrupt()

中断对象关联的线程,如果线程正在阻塞,则以异常方式通知 否则设置标志位

public static boolean

interrupted()

判断当前线程的中断标志位是否设置,调用后清除标志位

public boolean

isInterrupted()

判断对象关联的线程的标志位是否设置,调用后不清除标志位

public class InterruptTest {
    public static volatile boolean isQuit = false;

    static class RunnableT implements Runnable {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                //while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName()
                        + "正在操作转账!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }

            }
           System.out.println("及时中断转账!");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        RunnableT runnableT = new RunnableT();
        Thread thread = new Thread(runnableT,"张三:");
        thread.start();
        Thread.sleep(3000);
        System.out.println("老板来电话,得知对面是骗子!");

        thread.interrupt();

    }
}

运行结果:

thread 收到通知的方式有两种:

1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 常的形式通知,清除中断标志

当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程

2. 否则,只是内部的一个中断标志被设置,thread 可以通过Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志,Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

这种方式通知收到的更及时,即使线程正在 sleep 可以马上收到。

3.观察标志位是否被清除

interrupt()方法:表示可以中断线程,实际上只是给线程设置一个中断标志,但是线程依旧会执行。
interrupted()方法:Thread类的静态方法。检查当前线程的中断标志,返回一个boolean并清除中断状态,其连续两次调用的返回结果不一样,因为第二次调用的时候线程的中断状态已经被清除,会返回一个false。
isInterrupted()方法:测试线程是否被中断,不会清除中断状态。

使用Thrad.interrupted(),线程中断会清除标志位

public class InterruptTest2 {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.interrupted());
            }
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        thread.start();
        thread.interrupt();
    }
}

只有一开始是true,后面都是false,因为标志位被清除

使用Thread.currentThread().isInterrupted(),线程中断标记位不会被清除

public class InterruptTest2 {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().isInterrupted());
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        thread.start();
        thread.interrupt();
    }
}

全部都是true,因为标志位没有被清除

6.等待一个线程-join()

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。这时我们需要一个方法明确等待线程的结束

public class JoinTest {
    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, intnanos)

同理,但可以更高精度

7.获取当前线程引用

方法

说明

public static Thread currentThread();

返回当前线程对象的引用

8.休眠当前线程

也是我们比较熟悉一组方法,有一点要记得,因为线程的调度是不可控的,所以,这个方法只能保证实 际休眠时间是大于等于参数设置的休眠时间的。

 

方法

说明

public static void sleep(long millis) throws InterruptedException

休眠当前线程 millis 毫秒

public static void sleep(long millis, intnanos) throws

InterruptedException

可以更高精度的休眠

相关推荐

  1. Python中class方法的用法详解常见

    2024-05-02 21:36:07       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-02 21:36:07       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-02 21:36:07       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-02 21:36:07       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-02 21:36:07       20 阅读

热门阅读

  1. c++day7

    c++day7

    2024-05-02 21:36:07      14 阅读
  2. Python----列表删除

    2024-05-02 21:36:07       34 阅读
  3. 华纳云:ubuntu中fdisk找不到硬盘怎么解决?

    2024-05-02 21:36:07       13 阅读
  4. 如何通过编程学习走科技特长生的路线?

    2024-05-02 21:36:07       10 阅读
  5. C++基础—模版

    2024-05-02 21:36:07       9 阅读
  6. imread opencv

    2024-05-02 21:36:07       13 阅读
  7. 题解:CF1951E(No Palindromes)

    2024-05-02 21:36:07       10 阅读
  8. 安卓接入wwise

    2024-05-02 21:36:07       8 阅读