二、线程常用方法

本文详细介绍了Java线程的常用方法,包括getId、getName、setName、getState、setPriority、getPriority、sleep、join、yield、interrupt以及线程优先级的设置。通过实例展示了如何使用这些方法实现线程的插队、暂停、礼让、停止以及优先级调整,并讨论了线程停止的推荐做法。同时,文章还提供了代码示例,帮助理解线程的生命周期和行为控制。
摘要由CSDN通过智能技术生成

在这里插入图片描述

1、常用方法简览

修饰符和类型方法描述
public longgetId()返回此线程的标识符
public final StringgetName()返回此线程的名称
public final synchronized voidsetName(String name)将此线程的名称更改为 name
public Thread.StategetState()返回此线程的状态
public final voidsetPriority(int newPriority)更改此线程的优先级
public final intgetPriority()返回此线程的优先级
public static native voidsleep(long millis)使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行,但是其所拥有的监视器资源,比如锁还是持有不让出的),具体取决于系统定时器和调度程序的精度和准确性
public final synchronized voidjoin()等待这个线程死亡(就是霸道插队直到运行结束)
public static native voidyield()对调度程序的一个暗示,即当前线程愿意让出当前使用的处理器
public voidinterrupt()中断这个线程(你需要自行完成中断)
public final native booleanisAlive()测试这个线程是否活着

2、线程等待与通知

在Object类中有一些函数可以用于线程的等待与通知。

Object的线程等待方法如下:

  • wait():当一个线程A调用一个共享变量的 wait() 方法时, 线程A会被阻塞挂起,发生下面几种情况才会返回 :
    • 线程A调用了共享对象 notify() 或者 notifyAll() 方法
    • 其他线程调用了线程A的 interrupt() 方法,线程A抛出
  • wait(long timeout):这个方法相比 wait() 方法多了一个超时参数,它的不同之处在于,如果线程A调用共享对象的 wait(long timeout) 方法后,没有在指定的 timeout ms时间内被其它线程唤醒,那么这个方法还是会因为超时而返回。
  • wait(long timeout, int nanos):其内部调用的是 wait(long timout) 函数,nanos 是附加时间(ns)。

Object唤醒线程主要是下面两个方法:

  • notify():一个线程A调用共享对象的 notify() 方法后,会唤醒一个在这个共享变量上调用 wait 系列方法后被挂起的线程。 一个共享变量上可能会有多个线程在等待,具体唤醒哪个等待的线程是随机的。
  • notifyAll():不同于在共享变量上调用 notify() 函数会唤醒被阻塞到该共享变量上的一个线程,notifyAll() 方法则会唤醒所有在该共享变量上由于调用 wait 系列方法而被挂起的线程。

Thread类也提供了一个用于等待的方法:

  • join():如果一个线程A执行了 thread.join() 语句,其含义是:当前线程A等待 thread线程 终止之后从 thread.join() 返回。

来看一下 join() 官方的解释:Waits for this thread to die
就问你霸不霸道?!!!

1、CODE

package mii.thread.demo10;
/**
 * 测试插队:join
 */
public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("线程VIP来了" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestJoin tj = new TestJoin();

        // 启动我们的线程
        Thread thread = new Thread(tj);
        thread.start();
        
        // 主线程
        for (int i = 0; i < 10; i++) {
            if(i == 5){
                thread.join(); // 插队
            }
            System.out.println("main--" + i);
        }
    }
}

2、Result

在这里插入图片描述


3、线程休眠 sleep

Thread类中的静态方法,当一个执行中的线程A调用了Thread的sleep方法后,线程A会暂时让出指定时间的执行权,但是线程A所拥有的监视器资源,比如锁还是持有不让出的。指定的睡眠时间到了后该函数会正常返回,接着参与 CPU 的调度,获取到 CPU 资源后就可以继续运行。

  • sleep(毫秒) 指定当前线程阻塞的毫秒数
  • sleep 存在异常 InterruptedException 需要捕获或抛出
  • sleep 时间结束后线程进入就绪状态,继续参与 CPU 调度的竞争
  • 每个对象都有一个锁,sleep 不会释放锁

1、CODE

package mii.thread.demo10;
/**
 * 模拟倒计时
 */
public class TestSleep02 {
    public static void main(String[] args) throws InterruptedException {
        int i = 10;
        while(i >= 0){
            System.out.println(i--);
            Thread.sleep(1000);
        }
    }
}

2、Result

在这里插入图片描述


3、线程中断

  • 建议线程正常停止(利用次数,不建议死循环)
  • 建议使用标志位(设置一个标志位flag)
  • 不要使用 stopdestory等过时或JDK不建议使用的方法
  • void interrupt():中断线程,例如,当线程A运行时,线程B可以调用线程 interrupt() 方法来设置线程的中断标志为true 并立即返回。设置标志仅仅是设置标志, 线程A实际并没有被中断, 会继续往下执行。
  • boolean isInterrupted():检测当前线程是否被中断。
  • boolean interrupted():检测当前线程是否被中断,与 isInterrupted() 不同的是,该方法如果发现当前线程被中断,则会清除中断标志。

1、CODE

package mii.thread.demo10;
/**
 * 测试停止:stop
 * 1、建议线程正常停止(利用次数,不建议死循环)
 * 2、建议使用标志位(设置一个标志位flag)
 * 3、不要使用stop或destory等过时或JDK不建议使用的方法
 */
public class TestStop implements Runnable{
    // 1、设置一个标志位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while(flag){
            System.out.println("run...Thread-->" + i++);
        }
    }

    // 2、设置一个公开方法停止线程,转换标志位
    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop ts = new TestStop();

        new Thread(ts).start();

        for (int i = 0; i < 20; i++) {
            System.out.println("main...time-->" + i);
            if(i == 9){
                // 调用自己写的stop方法切换标志位,停止线程
                ts.stop();
                System.out.println("线程该停止了!");
            }
        }
    }
}

2、Result

在这里插入图片描述


4、让出优先权 yield

Thread类中的静态方法,当一个线程调用 yield 方法时,实际就是在暗示线程调度器当前线程请求让出自己的CPU ,但是线程调度器可以无条件忽略这个暗示。

  • 线程礼让,让当前正在执行的线程暂停,但不阻塞
  • 线程从运行状态转为就绪状态
  • 让 CPU 重新调度,礼让不一定成功,全看 CPU 心情

1、CODE

package mii.thread.demo10;
/**
 * 测试礼让:yield
 * 礼让不一定成功,看CPU心情
 */
public class TestYield implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        Thread.yield(); // 礼让
        System.out.println(Thread.currentThread().getName() + "线程停止执行");
    }

    public static void main(String[] args) {
        TestYield ty = new TestYield();

        new Thread(ty, "A").start();
        new Thread(ty, "B").start();
    }
}

2、Result

在这里插入图片描述


5、线程优先级 Priority

  • Java 提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行(优先级高低只影响被调用的概率,不是说优先级高就先执行,依然会出现性能倒置的情况,完全看 CPU 心情)

  • 线程的优先级用数字表示,范围从1~10

  • /** 线程可以具有的最小优先级. */
    public final static int MIN_PRIORITY = 1;
    
    /* 分配给线程的默认优先级. */
    public final static int NORM_PRIORITY = 5;
    
    /* 线程可以具有的最大优先级. */
    public final static int MAX_PRIORITY = 10; 
    
  • 使用以下方式改变或获取优先级

  • /* 修改此线程的优先级. */
    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
    
    /* 返回此线程的优先级. */
    public final int getPriority() {
        return priority;
    }
    

1、CODE

package mii.thread.demo11线程优先级;

/**
 * 测试线程优先级:priority
 */
public class TestPriority {
    public static void main(String[] args) {
        // 打印主线程优先级
        System.out.println(Thread.currentThread().getName() + "--->" +
                           Thread.currentThread().getPriority());

        Thread thread0 = new Thread(()->
              System.out.println(Thread.currentThread().getName() + "--->" +
                                 Thread.currentThread().getPriority()));
        Thread thread1 = new Thread(()->
              System.out.println(Thread.currentThread().getName() + "--->" +
                                 Thread.currentThread().getPriority()));
        Thread thread2 = new Thread(()->
              System.out.println(Thread.currentThread().getName() + "--->" +
                                 Thread.currentThread().getPriority()));
        Thread thread3 = new Thread(()->
              System.out.println(Thread.currentThread().getName() + "--->" +
                                 Thread.currentThread().getPriority()));
        // 先设置优先级再启动
        thread1.setPriority(1);
        thread2.setPriority(4);
        thread3.setPriority(Thread.MAX_PRIORITY);
        thread0.start();
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

2、Result

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纯纯的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值