讲解join()方法之前请确保对于即wait()/notify()/notifyAll()机制已熟练掌握。可以参考前面的笔记

join()方法的作用是等待线程销毁。join()方法反应的是一个很现实的问题,比如main线程的执行时间是1s,子线程的执行时间是10s,但是主线程依赖子线程执行完的结果,这时怎么办?可以像生产者/消费者模型一样,搞一个缓冲区,子线程执行完把数据放在缓冲区中,通知main线程,main线程去拿,这样就不会浪费main线程的时间了。另外一种方法,就是join()了。

join()方法之前的铺垫


上面的主线程想等待子线程,但是主线程先打印了,如果要实现主线程等待呢



用join()来解决


使用join成功的让主线程等待了,其实join内部还是使用的等待,所以join是放锁的




join()方法与异常


上面是ThreadB 调用a.join(),其实根据join的源码是当前B线程锁a线程对象,wait之后,B线程等待A线程notify,而要interrupt B线程就会出现异常,但是A线程还是继续,A线程是不受影响的




join(long)方法的使用


通过上面代码可以发现 join(long)  和 sleep(long)实现的效果是一样

join()方法的一个重点是要区分出和sleep()方法的区别。join(2000)也是可以的,表示调用join()方法所在的线程最多等待2000ms,两者的区别在于:

sleep(2000)不释放锁,join(2000)释放锁,因为join()方法内部使用的是wait(),因此会释放锁。看一下join(2000)的源码就知道了,join()其实和join(2000)一样,无非是join(0)而已:

  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;
}
}
}

第12行、第20行应该已经很清楚了

而sleep是不会释放锁的




sleep(long)方法不放锁


上面的例子都证明了  join 是放锁的,而sleep是不会放锁的

下面例子证明了join的另一种问题,原因是join是wait实现的,被其它线程唤醒后,会抢锁,而且是优先抢到锁





方法join()之后的代码提前运行-----出现意外


解释意外的发生情况



可以清楚的看到,出现的情况是多种多样的,原因就在于join会抢锁,执行完毕之后,就放锁然后执行锁之后的代码,也是由于线程的随机性,情况多种多样,join不是每次都会抢到锁






java多线程16:join()的使用的更多相关文章

  1. Java多线程中join、yield、sleep方法详解

    在Java多线程编程中,Thread类是其中一个核心和关键的角色.因此,对该类中一些基础常用方法的理解和熟练使用是开发多线程代码的基础.本篇主要总结一下Thread中常用的一些静态方法的含义及代码中的 ...

  2. JAVA多线程---wait() & join()

    题外话: interrupt()方法  并不能中断一个正常运行的线程!!! class myThread extends Thread{ @Override public void run(){ fo ...

  3. Java多线程16:线程组

    线程组 可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示: 线程组的作用是:可以批量管理线程或线程组对象,有效地对线 ...

  4. 转载:Java多线程中join方法的理解

    转载自:http://uule.iteye.com/blog/1101994 thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A ...

  5. Java多线程的join()

    假设在main线程里又起了一个thread1线程,在调用了thread1.start()之后: 如果在main线程里调用了thread1.join(),那么main线程将会block,直到thread ...

  6. Java多线程中join方法详解

    join()方法用于让当前执行线程等待join线程执行结束.其实现原理是不停的检查join线程是否存活,如果join线程存活则让当前线程永远等待. join()方法部分实现细节 while(isAli ...

  7. Java多线程中join方法的理解

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B. t.join( ...

  8. Java多线程学习——join方法的使用

    join在线程里面意味着“插队”,哪个线程调用join代表哪个线程插队先执行——但是插谁的队是有讲究了,不是说你可以插到队头去做第一个吃螃蟹的人,而是插到在当前运行线程的前面,比如系统目前运行线程A, ...

  9. java 多线程 Thread.join子线程结束父线程再运行;join(long):等待超时毫秒数

    Join的使用 目的:当子线程运行结束后,父线程才能再继续运行 /** * @ClassName ThreadJoinExample * @projectName: object1 * @author ...

随机推荐

  1. lsof命令详解(转)

    lsof命令详解(转) 上一篇 / 下一篇  2011-06-09 21:56:41 / 个人分类:Linux 查看( 351 ) / 评论( 0 ) / 评分( 0 / 0 ) 在Linux中,ls ...

  2. 十五分钟介绍 Redis数据结构

    下面是一个对Redis官方文档<A fifteen minute introduction to Redis data types>一文的翻译,如其题目所言,此文目的在于让一个初学者能通过 ...

  3. kickstart命令选项

    下面的选项可以放入kickstart文件.如果喜欢使用图形化的界面来创建kickstart文件,可以使用"Kickstart配置"应用程序.(注:如果某选项后面跟随了一个等号(=) ...

  4. saltstack 基础入门文档

    saltstack 和 Puppet Chef 一样可以让你同时在多台服务器上执行命令也包括安装和配置软件.Salt 有两个主要的功能:配置管理和远程执行.这里讲述了saltstack的基本使用方法. ...

  5. MFC添加自定义窗口消息

    原文链接: http://www.cnblogs.com/smartvessel/archive/2011/07/18/2109472.html 1. 在头文件stdafx.h中增加一个自定义消息宏 ...

  6. html5+php实现文件拖动上传功能

    界面样式我是参考了一个国外的相册网站,改动不大,只是把鸟语转换成中文,以及上传时的样式也进行了改动,之所以选这个的原因就是,我很容易做扩展,它支持3种方式添加图片,一种拖拽上传,一种常规的选择文件上传 ...

  7. C#文件下载(实现断点续传)

    public class WebDown { /// 下载文件方法 /// 文件保存路径和文件名 /// 返回服务器文件名 public static bool DeownloadFile(strin ...

  8. python md5 问题(TypeError: Unicode-objects must be encoded before hashing)

    import hashlib import sys def md5s(): m=hashlib.md5() strs=sys.argv[1] m.update(strs.encode("ut ...

  9. mysql错误号代表的含义

    1005:创建表失败1006:创建数据库失败1007:数据库已存在,创建数据库失败1008:数据库不存在,删除数据库失败1009:不能删除数据库文件导致删除数据库失败1010:不能删除数据目录导致删除 ...

  10. logstash 如何处理 mongodb 导出来的 _id value数据。 how to custom fields of logstash by mongo mapreduce exported data.(example format: {_id:"xxx"} , value:{})

    input { file { path => "c:\aa.json" start_position => "beginning" #sincedb ...