美文网首页
Thread中yield()方法, join()方法- 理解记录

Thread中yield()方法, join()方法- 理解记录

作者: 4762d2980c91 | 来源:发表于2016-09-01 11:22 被阅读1625次

    yield()方法

    /**
     * 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();
    

    • 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.

    翻译: 提示系统调度器==当前线程==愿意放弃其正在使用的处理器资源.调度器可以忽略这个提示.(注:放弃正在使用的处理器资源也就表示一个线程将由运行状态转到就绪状态,同时也说明此线程有可能会继续被分配到处理器资源继续执行)

    静态方法: 调用方式Thread.yield(); 从调用方式要理解的一个关键点是: 当前线程,那么这里的当前线程到底是哪个线程呢.比如我有代码如下:

    public class TestYield {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(){
                @Override
                public void run() {
                        try {
                            System.out.println("线程执行---");
                            sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
            };
            System.out.println(System.currentTimeMillis());
            thread.start();
            Thread.yield();
            System.out.println(System.currentTimeMillis());
        }
    }
    

    当如上代码执行的时候, Thread.yield()执行时,是哪个线程愿意放弃正在
    使用的处理器资源呢,这里是主线程.也就是说Thread.yield()在哪个线程中被调用就
    表示哪个线程愿意放弃处理器资源.


    join()方法

    join() : 当前线程暂停执行

    /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @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() throws InterruptedException {
        join(0);
    }
    

    join(long millis): 当前线程暂停执行,直到millis毫秒之后继续执行

    /**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * <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 synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;
    
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
    
        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
    

    join(long millis, int nanos): 当前线程执行暂停, 直到millis+namos后继续

    /**
     * Waits at most {@code millis} milliseconds plus
     * {@code nanos} nanoseconds for this thread to die.
     *
     * <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
     *
     * @param  nanos
     *         {@code 0-999999} additional nanoseconds to wait
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative, or the value
     *          of {@code nanos} is not in the range {@code 0-999999}
     *
     * @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 synchronized void join(long millis, int nanos)
    throws InterruptedException {
    
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
    
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
    
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }
    
        join(millis);
    }
    

    实例代码:

    public class TestJoin {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(){
                @Override
                public void run() {
                        try {
                            System.out.println("线程执行---");
                            sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
            };
            System.out.println("开始:" + System.currentTimeMillis());
            thread.start();
            thread.join(3000);
            System.out.println("结束:" + System.currentTimeMillis());
        }
    }
    

    join()是实例方法, 只能在实例级别被调用, 那么在上述例子中,当执行thread.join()
    方法时, 被暂停的是主线程还是thread线程呢? 结果是主线程被暂停. 也就是说被暂停
    的线程还是调用执行这句代码的线程.也就是说调用线程被暂停,而join()方法的所属
    实例继续执行.如果join()方法不传参数,那么主线程会等待直到thread线程执行完毕后
    才会继续执行,否则就是暂停传入时间后继续执行.
    如果你想打断这种暂停, 那么你可以在thread中调用notify(),notifyAll()方法来打断.
    但是就从注释中我们也可以看出并不推荐在线程实例上条用notify()或者notifyAll()方法.

    补充:从源码中我们也可以看出join()方法其实是调用的Object的wait()方法来实现的,那么他又是在什么时候被notify的呢(我们知道被wait的线程必须被notify才会继续执行).从注解(==As a thread terminates the

    {@code this.notifyAll} method is invoked==)可知, 当一个线程终止时,他的notifyAll()方法会被调用

    相关文章

      网友评论

          本文标题:Thread中yield()方法, join()方法- 理解记录

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