12 线程休眠 sleep,线程礼让 yield, Thread.join()的使用,线程过期的suspend()、resume()和stop()

线程休眠 sleep

  • sleep(long)指定当前线程阻塞的毫秒数
  • sleep存在异常InterruptException
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延时
  • 每个对象都有一把锁,sleep不会释放锁

线程礼让 yield

yield() 暂停当前线程,使当前线程从running状态变为Ready状态,

让cpu重新调度。至于cpu选中那个线程执行是随机的,完全取决于cpu调度。

public class ThreadYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield,"A").start();
        new Thread(myYield,"B").start();

    }
}

class MyYield implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " start...");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + " stop...");
    }
}

执行结果

多执行几次,会发现不一样的结果

A start...
B start...
A stop...
B stop...

Thread.join()的使用

一个线程A执行了B.join()时,当前线程A等待B线程终止之后才执行线程A剩下部分。

join()保证线程B的可见性,即线程B中修改的变量,线程A可见。

/**
 * Thread join方法
 */
public class Join {
    public static void main(String[] args) throws Exception {
        Thread previous = Thread.currentThread();
        for (int i = 0; i < 10; i++) {
            // 每个线程拥有前一个线程的引用,需要等待前一个线程终止,才能从等待中返回
            Thread thread = new Thread(new Domino(previous), String.valueOf(i));
            thread.start();
            previous = thread;
        }
        TimeUnit.SECONDS.sleep(5);
        System.out.println(Thread.currentThread().getName() + " terminate.");
    }

    static class Domino implements Runnable {
        private Thread thread;

        public Domino(Thread thread) {
            this.thread = thread;
        }

        public void run() {
            try {
                thread.join();
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName() + " terminate.");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
main terminate.
0 terminate.
1 terminate.
2 terminate.
3 terminate.
4 terminate.
5 terminate.
6 terminate.
7 terminate.
8 terminate.
9 terminate.

Process finished with exit code 0

每个线程终止的前提是前驱线程的终止,每个线程等待前驱线程 终止后,才从join()方法返回。

join方法相当于插队执行,最早插队的是main,依次为0-9,故执行顺序如上。

a.join()方法,等待a线程执行完毕,再执行其他线程,其他线程阻塞

public class ThreadJoin {

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

        Thread t1 = new Thread(myJoin, "张三");
        t1.start();

        for (int i = 0; i < 200; i++) {
            Thread.sleep(50);
            System.out.println("王五 执行到 " + i);
            if (i==100){
                t1.join();
            }
        }

    }

}

class MyJoin implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 执行到 " + i);
        }
    }
}

线程过期的suspend()、resume()和stop()

暂停 suspend()

恢复 resume()

停止 stop()

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 过期的方法
 * 暂停 suspend()
 * 恢复 resume()
 * 恢复 stop()
 * 像音乐播放器的按键一样
 */
public class Deprecated {
    public static void main(String[] args) throws Exception {
        DateFormat format = new SimpleDateFormat("HH:mm:ss");
        Thread printThread = new Thread(new Runner(), "PrintThread");
        printThread.setDaemon(true);
        printThread.start();
        TimeUnit.SECONDS.sleep(3);
        // 将PrintThread进行暂停,输出内容工作停止
        printThread.suspend();
        System.out.println("main suspend PrintThread at " + format.format(new Date()));
        TimeUnit.SECONDS.sleep(3);
        // 将PrintThread进行恢复,输出内容继续
        printThread.resume();
        System.out.println("main resume PrintThread at " + format.format(new Date()));
        TimeUnit.SECONDS.sleep(3);
        // 将PrintThread进行终止,输出内容停止
        printThread.stop();
        System.out.println("main stop PrintThread at " + format.format(new Date()));
        TimeUnit.SECONDS.sleep(3);
    }

    static class Runner implements Runnable {
        @Override
        public void run() {
            DateFormat format = new SimpleDateFormat("HH:mm:ss");
            while (true) {
                System.out.println(Thread.currentThread().getName() + " Run at " +
                        format.format(new Date()));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
//执行结果
PrintThread Run at 21:30:27
PrintThread Run at 21:30:28
PrintThread Run at 21:30:29
main suspend PrintThread at 21:30:30
PrintThread Run at 21:30:33
main resume PrintThread at 21:30:33
PrintThread Run at 21:30:34
PrintThread Run at 21:30:35
main stop PrintThread at 21:30:36

Process finished with exit code 0

不建议使用的原因主要有:以suspend()方法为例,在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题。同样,stop()方法在终结 一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

EngineerForSoul

你的鼓励是我孜孜不倦的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值