zoukankan      html  css  js  c++  java
  • Java中join()方法的理解

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。

    比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

    t.join();      //调用join方法,等待线程t执行完毕
    t.join(1000);  //等待 t 线程,等待时间是1000毫秒。

    下面是一段JDK中的代码:

        /**
         *  Waits at most <code>millis</code> milliseconds for this thread to  
         * die. A timeout of <code>0</code> means to wait forever.    
         */
        
        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() 方法是没有作用的,将直接继续向下执行

    Join方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程 ,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁

    通过下面一段代码解释:

    package ThreadTest;
    
    import static java.lang.Thread.currentThread;
    import static java.lang.Thread.sleep;
    
    /**
     * Created with IntelliJ IDEA.
     * User: Blank
     * Date: 14-3-28
     * Time: 下午7:49
     */
    public class TestJoin implements Runnable {
    
    
        public static void main(String[] sure) throws InterruptedException {
            Thread t = new Thread(new TestJoin());
            long start = System.currentTimeMillis();
            t.start();
            t.join(1000);//等待线程t 1000毫秒
            System.out.println(System.currentTimeMillis()-start);//打印出时间间隔
            System.out.println("Main finished");//打印主线程结束
        }
    
        @Override
        public void run() {
           // synchronized (currentThread()) {
                for (int i = 1; i <= 5; i++) {
                    try {
                        sleep(1000);//睡眠5秒,循环是为了方便输出信息
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("睡眠" + i);
                }
                System.out.println("TestJoin finished");//t线程结束
            }
        //}
    }

    在注释掉synchronized修饰的run方法后,打印信息如下:

    可以看到main线程等待了t线程1000毫秒之后,结束了,随后是t线程打印的数据。

    那么如果加上run方法的synchronized那条语句呢?结果如下:

    由于先调用了t.start()方法,线程进入synchronized代码段,main线程等待一秒以后,还是得不到线程t的对象锁,只能继续等待,直到线程t结束,释放锁。这里可以明确看到main线程等待时间是5000ms,有些文章里写的是t线程执行时间+join方法指定的时间(5000+1000 ),其实不是的,这里可以很清晰的看到,main线程等待时间只有5000ms,看到有的文章说join调用的wait也是需要获取对象锁的。

    JDK源代码中wait操作是

    public final native void wait(long timeout) throws InterruptedException;

    wait内部实现应该是用synchronized,等待时间是5000+1000就好解释了,搞不明白。

    此处存疑。

  • 相关阅读:
    linux___用户管理
    linux基础_vim命令
    linux
    linux_centos安装
    python基础1_哈希碰撞的认识
    oop对象,面向对象
    Oracle数据库—— 事务处理与并发控制
    Oracle数据库——索引、视图、序列和同义词的创建
    Oracle数据库——触发器的创建与应用
    Oracle数据库—— 存储过程与函数的创建
  • 原文地址:https://www.cnblogs.com/aboutblank/p/3631453.html
Copyright © 2011-2022 走看看