美文网首页
join方法与yield方法

join方法与yield方法

作者: 大海孤了岛 | 来源:发表于2017-05-10 19:53 被阅读148次

Join方法

  • 定义:等待被调用的线程结束。具体来说,t.join()表示阻塞调用此方法的线程,直到线程t完成为此,方可继续0。

  • 样例一:计算子线程的运行时间

public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + ": start");
        long start = System.currentTimeMillis();
        Thread t = new Thread(new MyRunnable());
        t.start();
        //阻塞主线程直到子线程完成
        t.join();
        long end = System.currentTimeMillis();
        System.out.println("子线程花费的时间是:" + (end - start) + "ms");
        System.out.println(Thread.currentThread().getName() + ": end");
    }

    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": start");
            for (int i = 0; i < 100000; i ++);
            System.out.println(Thread.currentThread().getName() + ": end");
        }
    }
}

输出结果:
main: start
Thread-0: start
Thread-0: end
子线程花费的时间是:3ms
main: end
  • 源码分析

我们查看join方法的源码如下:

public final void join() throws InterruptedException {
        join(0);
}

默认设置时长为0,我们继续查看join(n)方法的源码:

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");
    }
    //设置时长为0时,会一直阻塞,直到被设置的线程结束
    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            //wait方法并不能准确地等待,可能会被唤醒,因此需要多次检查判断
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

我们可以看到它是通过wait(n)方法来保证当前线程的等待。对于上面的例子:main线程调用t.join()时,main线程会获得对象t的锁,然后调用该对象的wait(等待时间),直到该对象唤醒main线程。

  • t.join(delay)方法中,当等待时间达到delay时,不管子线程是否执行完毕,主线程都会继续执行。
public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + ": start");
        Thread t = new Thread(new MyRunnable());
        t.start();
        //设置等待时间为3s
        t.join(3000);
        System.out.println(Thread.currentThread().getName() + ": end");
    }

    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": start");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ": end");
        }
    }
}

运行结果:
main: start
Thread-0: start
main: end
Thread-0: end

如上,子线程运行的时间为5s,而主线程设置的等待时间为3s,因此当等待时间达到后,主线程会立即执行。

Yield方法

  • 定义:使当前线程从执行状态(运行状态)变为可执行状态(就绪状态)。

  • 样例

public class YieldTest {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + ": start");
        long start = System.currentTimeMillis();
        Thread t = new Thread(new MyRunnable());
        t.start();
        //让出CPU给子线程执行任务,直到结束
        while (Thread.activeCount() > 1)
            Thread.yield();
        long end = System.currentTimeMillis();
        System.out.println("子线程花费的时间是:" + (end - start) + "ms");
        System.out.println(Thread.currentThread().getName() + ": end");
    }

    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ": start");
            for (int i = 0; i < 100000; i ++);
            System.out.println(Thread.currentThread().getName() + ": end");
        }
    }

}

输出结果:
main: start
Thread-0: start
Thread-0: end
子线程花费的时间是:3ms
main: end
  • yield方法的操作流程:

先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把CPU的占有权交给次线程,否则继续运行原来的线程,所以yield()方法称为“退让”,它把运行机会让给了同等级的其他线程。

  • yield方法与sleep方法的区别
  • sleep方法使当前运行中的线程睡眠一段时间,进入不可运行状态,这段时间的长短由程序设定,yield方法使当前线程让出CPU占有权,但让出的时间是不可设定的。
  • sleep 方法允许较低优先级的线程获得运行机会,但yield()方法执行时,当前线程仍处在可运行状态,所以不可能让出较低优先级的线程此时获取CPU占有权。

相关文章

  • join方法与yield方法

    Join方法 定义:等待被调用的线程结束。具体来说,t.join()表示阻塞调用此方法的线程,直到线程t完成为此,...

  • sleep(),wait(),join(),yield(),in

    sleep(),wait(),join(),yield(),interrupt()方法简介 sleep()是Thr...

  • 线程

    线程与进程的区别: 理解线程的优先权 yield()方法 join()方法 线程的生命周期: sleep和wait...

  • join()方法和yield()方法

    join():当A线程执行到了B线程的 .join()方法时,A就好等待,当B线程都执行完,A才会执行。 join...

  • Thread.join和Thread.yield

    在Thread类提供的方法中,join方法和yield方法应该相对比较不好理解一点的,今天谈谈我的理解 join方...

  • 线程

    join方法加入线程方法 interrupt终止线程 yield礼让方法 暂不介绍啦,因为具体要看CPU 线程设置...

  • Java线程的基本方法

    线程相关的基本方法有wait,notify,notifyAll,sleep,join,yield 等。 线程等待(...

  • 线程状态及其常用方法

    1、线程状态图: 2、线程常用方法sleep(),wait(),join(),yield(): 线程停止: jav...

  • Java 中如何正确停止线程

    背景 这里将着重描述如何停止一个线程,同时,顺带对其他线程方法如join、yield、wait方法也做一个总结。 ...

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

    yield()方法 A hint to the scheduler that the current thread...

网友评论

      本文标题:join方法与yield方法

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