美文网首页
线程Thread的sleep,join,yield方法

线程Thread的sleep,join,yield方法

作者: 陈萍儿Candy | 来源:发表于2020-10-29 10:22 被阅读0次

一:sleep(3000);方法和object.wait(10000);区别
1.obj.wait方法会释放锁 必须在sychronized获取到该obj锁的状态下调用obj.wait方法,是Object的方法
2.sleep方法不会释放锁,不用在sychronized获取锁时调用,可以在任何地方使用,是Thread类的方法
sleep,wait调用后都会暂停当前线程并让出cpu的执行时间,但不同的是sleep不会释放当前持有的对象的锁资源,到时间后会继续执行,而wait会放弃所有锁并需要notify/notifyAll后重新获取到对象锁资源后才能继续执行;

Thread.sleep(10000);是静态方法
obj.wait是实例方法;

它们都可以被interrupted方法中断。

Thread.Sleep(1000) 意思是在未来的1000毫秒内本线程不参与CPU竞争,1000毫秒过去之后,这时候也许另外一个线程正在使用CPU,那么这时候操作系统是不会重新分配CPU的,直到那个线程挂起或结束,即使这个时候恰巧轮到操作系统进行CPU 分配,那么当前线程也不一定就是总优先级最高的那个,CPU还是可能被其他线程抢占去。另外值得一提的是Thread.Sleep(0)的作用,就是触发操作系统立刻重新进行一次CPU竞争,竞争的结果也许是当前线程仍然获得CPU控制权,也许会换成别的线程获得CPU控制权。

wait(1000)表示将锁释放1000毫秒,到时间后如果锁没有被其他线程占用,则再次得到锁,然后wait方法结束,执行后面的代码,如果锁被其他线程占用,则等待其他线程释放锁。注意,设置了超时时间的wait方法一旦过了超时时间,并不需要其他线程执行notify也能自动解除阻塞,但是如果没设置超时时间的wait方法必须等待其他线程执行notify。

image.png

二:join方法:
用处1:Thread.join方法可以让多线程按照指定的顺序执行
1.测试代码:

class ThreadTest2  extends Thread{
    private int I ;
    // 上一个线程
    private Thread previousThread;

    public ThreadTest2(int i, Thread previousThread) {
        this.i = I;
        this.previousThread = previousThread;
    }

    @Override
    public void run() {
        super.run();
        // 先注释掉join代码
//        try {
//            previousThread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        System.out.println("num:"+i);
    }

    public static void main(String[] args) {
        Thread previousThread = Thread.currentThread();
        for (int i = 0;i < 10;i++){
            ThreadTest2 threadTest2 = new ThreadTest2(i,previousThread);
            threadTest2.start();
            previousThread = threadTest2;
        }

    }
}

如上代码注释掉join代码运行一遍,输出结果:


image.png

把注释掉的join代码放开,运行结果如下:


image.png
运行的结果按照递增的顺序展示出来

在子线程ThreadTest2中调用previousThread.join();会阻塞调用该方法的线程,直到线程previousThread结束,此线程再继续
Thread类中的join方法源码:

/**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * 等待最多{@code millis}毫秒这个线程死亡。{@code 0}的超时意味着永远等待。
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join(long millis) throws InterruptedException {
        synchronized(lock) {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                lock.wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                lock.wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
        }
    }

源码分析:synchronized(lock) 中的lock是谁,有的说是privirousThread线程,lock.wait(0);等待的就是privirousThread线程对象,又说这个对象在privirousThread在自己线程是持有的,等privirousThread线程结束时会notifyAll所有这个锁的等待的线程,那怎么进去synchronized(lock)的?????

三:yeild 放弃,让出
源码:

/**
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     *  提示调度程序当前线程愿意放弃当前对处理器的使用。调度器可以忽略这个提示。
     *
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
    public static native void yield();

yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,有可能是其他人先上车了,也有可能是Yield先上车了。

但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,

最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。
测试代码参考:
https://www.cnblogs.com/java-spring/p/8309931.html

相关文章

网友评论

      本文标题:线程Thread的sleep,join,yield方法

      本文链接:https://www.haomeiwen.com/subject/ulpvmktx.html