A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© yuehaotian 中级黑马   /  2013-12-21 19:56  /  2252 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

多线程总 join  和 wanit 都可以让线程冻结,那么他们有什么区别呢??

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

6 个回复

倒序浏览

(1)方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答。
    自从接触Java多线程,一直对Join理解不了。JDK是这样说的:
   join
    public final void join(long millis)throws InterruptedException
    Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
大家能理解吗? 字面意思是等待一段时间直到这个线程死亡,我的疑问是那个线程,是它本身的线程还是调用它的线程的,上代码:
package concurrentstudy;
/**
*
* @author vma
*/
public class JoinTest {
    public static void main(String[] args) {
        Thread t = new Thread(new RunnableImpl());
        t.start();
        try {
            t.join(1000);
            System.out.println("joinFinish");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
     
        }
    }
}
class RunnableImpl implements Runnable {

    @Override
    public void run() {
        try {
            System.out.println("Begin sleep");
            Thread.sleep(1000);
           System.out.println("End sleep");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
结果是:
Begin sleep
End sleep
joinFinish
明白了吧,当main线程调用t.join时,main线程等待t线程,等待时间是1000,如果t线程Sleep 2000呢
public void run() {
        try {
            System.out.println("Begin sleep");
            // Thread.sleep(1000);
            Thread.sleep(2000);
           System.out.println("End sleep");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
结果是:
Begin sleep
joinFinish
End sleep
也就是说main线程只等1000毫秒,不管T什么时候结束,如果是t.join()呢, 看代码:   
public final void join() throws InterruptedException {
    join(0);
    }
就是说如果是t.join() = t.join(0) 0 JDK这样说的 A timeout of 0 means to wait forever 字面意思是永远等待,是这样吗?
其实是等到t结束后。
这个是怎么实现的吗? 看JDK代码:
    /**
     * Waits at most <code>millis</code> milliseconds for this thread to
     * die. A timeout of <code>0</code> means to wait forever.
     *
     * @param      millis   the time to wait in milliseconds.
     * @exception  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方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程,比如退出后。

这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁,如果拿不到它是无法wait的,刚开的例子t.join(1000)不是说明了main线程等待1秒,如果在它等待之前,其他线程获取了t对象的锁,它等待时间可不就是1毫秒了。上代码介绍:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package concurrentstudy;
/**
*
* @author vma
*/
public class JoinTest {
    public static void main(String[] args) {
        Thread t = new Thread(new RunnableImpl());
       new ThreadTest(t).start();
        t.start();
        try {
            t.join();
            System.out.println("joinFinish");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
     
        }
    }
}
class ThreadTest extends Thread {

    Thread thread;

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

    @Override
    public void run() {
        holdThreadLock();
    }

    public void holdThreadLock() {
        synchronized (thread) {
            System.out.println("getObjectLock");
            try {
                Thread.sleep(9000);

            } catch (InterruptedException ex) {
             ex.printStackTrace();
            }
            System.out.println("ReleaseObjectLock");
        }

    }
}

class RunnableImpl implements Runnable {

    @Override
    public void run() {
        try {
            System.out.println("Begin sleep");
            Thread.sleep(2000);
           System.out.println("End sleep");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }
}
在main方法中 通过new ThreadTest(t).start();实例化ThreadTest 线程对象, 它在holdThreadLock()方法中,通过 synchronized (thread),获取线程对象t的锁,并Sleep(9000)后释放,这就意味着,即使
main方法t.join(1000),等待一秒钟,它必须等待ThreadTest 线程释放t锁后才能进入wait方法中,它实际等待时间是9000+1000 MS
运行结果是:
getObjectLock
Begin sleep
End sleep
ReleaseObjectLock
joinFinish

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
我觉得简单的说就是:

join()方法使调用该方法的线程在此之前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行。注意该方法也要捕获异常。
比如A线程执行了B线程的join方法,那么A就会等会,等B执行完了,A再继续执行。

wait一般用于Synchronized中。wait()方法使当前线程暂停执行并释放对象锁标志,让其他线程可以进入Synchronized数据块,当前线程被放入对象等待池中。当调用 notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中的线程能够获取锁标志。

希望能对你有所帮助。。

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
join()方法:让等待该线程终止。
当A线程执行到了B线程的join方法时,A就会等待。
等B线程都执行完,A才会继续执行。
join可以用来临时加入线程执行。也就是A线程是被B线程中断的,然后B执行完之后A自动开始继续执行。

wait()方法是A线程执行到自己的wait()方法的时候,自己进入到等待状态。
而且wait之后的线程A不会自动继续执行,它需要另外一个线程B来唤醒之后才能执行。

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
简单来说,join()方法使调用该方法的线程在此之前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行。注意该方法也要捕获异常。
wait方法用于协调多个线程对共享数据的存取,所以必须在Synchronized语句块内使用wait方法
wait()方法使当前线程暂停执行并释放对象锁标志

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
看来很详细
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马