Thread类的常用方法

本文详细介绍了Java中的线程管理,包括Thread类的常用构造方法和属性,如线程的ID、名称、状态和优先级。重点讨论了run()与start()的区别,以及如何获取当前线程引用、中断线程、使用join()等待线程和使线程休眠。文中通过实例展示了如何通过中断标志和异常来中断线程,以及join()和sleep()方法的使用场景。
摘要由CSDN通过智能技术生成


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

Thread 类的对象就是用来描述一个线程的执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度、线程管理

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(), "这是我的名字");

Thread 的几个常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台进程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()
  • ID 是线程的唯一标识,不同线程不会重复
  • 名称是各种调试工具用到
  • 状态表示线程当前所处的一个情况
  • 优先级高的线程理论上来说更容易被调度到,和线程调度相关
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行
  • 是否存活,即简单的理解,为 run 方法是否运行结束了。但是注意,此时Thread对象还没有销毁
  • 是否被中断,在下面有
public class test2 {

    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run(){
                for(int i = 0 ; i < 5 ;i++){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        System.out.println(t.getId());
        System.out.println(t.getName());
        System.out.println(t.getState());
        System.out.println(t.getPriority());
        System.out.println(t.isDaemon());
        System.out.println(t.isAlive());
        System.out.println(t.isInterrupted());

        t.start();
        System.out.println("==================");

        System.out.println(t.getId());
        System.out.println(t.getName());
        System.out.println(t.getState());
        System.out.println(t.getPriority());
        System.out.println(t.isDaemon());
        System.out.println(t.isAlive());
        System.out.println(t.isInterrupted());
    }
}
//运行结果
12
Thread-0
NEW
5
false
false
false
==================
12
Thread-0
RUNNABLE
5
false
true
false

run() 和 start() 的区别

  • 调用 start 方法才是创建了线程,有了新的执行流
  • 调用 run 方法只是一个普通的方法调用,不涉及新线程的创建(仍然是在原来的线程中)

获取当前线程的引用

public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
   }
}

中断一个线程

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

  1. 通过共享的标记来进行沟通
  2. 调用 interrupt() 方法来通知

示例一:

public class test3{

    private static class MyRunnable implements Runnable {

        public volatile boolean isQuit = false;

        @Override
        public void run() {
            while (!isQuit) {
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
       public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "大毛");
        System.out.println(Thread.currentThread().getName());
        thread.start();
        Thread.sleep(1 * 1000);
        System.out.println(Thread.currentThread().getName());
        target.isQuit = true;
    }
}

示例2:

public class test4{
    private static class MyRunnable 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();
                    System.out.println(Thread.currentThread().getName());
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "二毛");
        System.out.println(Thread.currentThread().getName());
        thread.start();
        Thread.sleep(1 * 1000);
        System.out.println(Thread.currentThread().getName());
        thread.interrupt();
    }
}

这里说一下第二种情况:

  1. 通过 thread 对象调用 interrupt() 方法通知该线程停止运行

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

    1. 如果线程调用了 wait / join / sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志
    2. 否则,只是内部的一个中断标志被设置,thread 可以通过
      1. Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
      2. Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

示例3:

public class test5{
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("通过异常收到了中断情况");
            }
            for (int i = 0; i < 5; 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();
    }
}
//运行结果——通过异常收到中断通知,并且标志位被清
false
false
false
false
false

示例4:

public class test6{
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; 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,因为标志位被清
true
false
false
false
false

示例5:

public class test7{
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; 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,因为标志位没有被清
true
true
true
true
true

方法:

方法说明
public void interrupt()中断对象关联的线程,如果线程正在阻塞,则以异常方式通知,否则设置标志位
public static boolean interrupted()判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean isInterrupted()判断对象关联的线程的标志位是否设置,调用后不清除标志位

等待一个线程 — join()

当多个线程被创建的时候,每个线程都是一个独立的执行流。这些线程中执行的先后顺序是不确定的,取决于系统的调度

等待线程机制就是无法保证哪个线程先执行,但是可以确定线程的“结束顺序”

public class test8 {

    public static void main(String[] args) throws InterruptedException {
        Runnable target = () -> {
            for (int i = 0; i < 5; 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, "线程1");
        Thread thread2 = new Thread(target, "线程2");
        System.out.println("线程1开始工作");
        thread1.start();
        thread1.join();
        System.out.println("线程1结束,线程2开始工作");
        thread2.start();
        thread2.join();
        System.out.println("线程2结束");
    }
}
//运行结果
线程1开始工作
线程1
线程1
线程1
线程1
线程1
线程1
线程1结束,线程2开始工作
线程2
线程2
线程2
线程2
线程2
线程2
线程2结束

因为, thread1先调用了 join(),所以要等 thread1 结束之后thread2才能开始工作

方法说明
public void join()等待线程结束
public void join(long millis)等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos)同理

休眠当前线程 — sleep()

因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的

方法说明
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());
   }
}

没有调用 sleep() 的线程随时可能会被调度到CPU上执行
当某线程调用sleep()后,就会进入等待状态。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值