join在线程里面意味着“插队”,哪个线程调用join代表哪个线程插队先执行——但是插谁的队是有讲究了,不是说你可以插到队头去做第一个吃螃蟹的人,而是插到在当前运行线程的前面,比如系统目前运行线程A,在线程A里面调用了线程B.join方法,则接下来线程B会抢先在线程A面前执行,等到线程B全部执行完后才继续执行线程A。

而在JDK的解释中,join方法被解释成等待这个线程死亡,也就是等待这个线程全部执行完后才继续执行接下来的进程。

public class Test1 implements Runnable{

    @Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
} public static void main(String[] args) throws InterruptedException {
Thread thread1=new Thread(new Test1(),"线程一");
Thread thread2=new Thread(new Test1(),"线程二");
Thread thread3=new Thread(new Test1(),"线程三");
thread1.start();
thread2.start();
thread3.start(); System.out.println("------------------主线程到此-------------------");
/*thread2.join(); */ for (int i = 0; i < 20; i++) {
System.out.println("主线程"+i);
}
} }

在上面这个例子中,在主线程里面开启了3个子线程,结果是主线程先执行完再执行其他线程。

加上让线程2先执行完再执行主线程join后

public class Test1 implements Runnable{

    @Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
} public static void main(String[] args) throws InterruptedException {
Thread thread1=new Thread(new Test1(),"线程一");
Thread thread2=new Thread(new Test1(),"线程二");
Thread thread3=new Thread(new Test1(),"线程三");
thread1.start();
thread2.start();
thread3.start(); System.out.println("------------------主线程到此-------------------");
thread2.join(); //让线程2先执行完主线程才能继续执行 for (int i = 0; i < 20; i++) {
System.out.println("主线程"+i);
}
} }

结果是

/**
* join的用法,哪个线程调用join哪个线程就插队先执行
*/ public class Test{ public static void main(String[] args) throws InterruptedException {
//开启Father线程,满足Father需求
new Thread(new Father()).start();
} } class Father implements Runnable{ @Override
public void run() {
System.out.println("老爸要抽烟,发现没烟了,给了100块让儿子去买中华......");
Thread son=new Thread(new Son()); //让儿子去买烟
son.start(); //开启儿子线程后,儿子线程进入就绪状态等待CPU调度,不一定立即执行儿子线程,所以可能会出现儿子没把烟买回来老爸就有烟抽了
/* try {
son.join(); //让儿子先插队去买烟
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("儿子不见了,报警寻找");
}*/
System.out.println("老爸接过烟,把零钱给了儿子");
System.out.println("儿子很开心,出门去了游戏厅");
}
} class Son implements Runnable{ @Override
public void run() {
System.out.println("儿子接过钱蹦跶出了门");
System.out.println("路过游戏厅玩了10秒钟");
for (int i = 1; i <= 10; i++) {
System.out.println(i+"秒");
try {
Thread.sleep(1000); //此时休眠可能会让其他线程进行,出错率增加,通过join方法解决
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("赶紧去买烟");
System.out.println("回家把烟给老爸");
}
}

加入了join方法后,运行结果正确

try {
son.join(); //让儿子先插队去买烟
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("儿子不见了,报警寻找");
}

Java多线程学习——join方法的使用的更多相关文章

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

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

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

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

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

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

  4. Java多线程学习——wait方法(信号灯法/生产者消费者模式)

    信号灯法:以一个标志位来判断是否执行还是等待 public class TV { private String voice; //内容 private boolean flag=false; //信号 ...

  5. Java多线程学习——wait方法(管道法/生产者消费者模式)

    简单介绍管道法: 生产者生产数据输送到管道,消费者从管道拿出数据,管道为空消费者等待,管道满生产者生产,消费者消费生产者生产,生产者生产消费者消费. public class Corn { //要生产 ...

  6. java多线程学习

    在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. 一.扩展java.lang.Thread类 package com.multithread.lea ...

  7. Java多线程学习(吐血超详细总结)

    本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的 ...

  8. Java多线程学习(转载)

    Java多线程学习(转载) 时间:2015-03-14 13:53:14      阅读:137413      评论:4      收藏:3      [点我收藏+] 转载 :http://blog ...

  9. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

随机推荐

  1. Java学习03-进制学习

    计算机中是以二进制来进行数据传递的,二进制分为二进制.八进制.十进制.十六进制 而他们之间如何进行转换呢,二进制作为元,其他进制都是经二进制进行换算的,所以无论什么进制之间的转换都是先转换为二进制,再 ...

  2. gdb命令小结

    GDB命令小结 gdb <filename> : 调试指定程序文件 r : run 的简写,运行被调试程序, 如果此前没有下过断点,则执行完整个程序:如果有断点, 则程序暂停在第一个可用断 ...

  3. jquery easyui datagrid 远程加载数据----把主键渲染为值遇到的问题及解决方案

    起因:数据库中一些字段存的是代表具体值的数字,需要渲染为具体值 monggodb中的字典 mysql中存放的值为:expertin代表教练擅长的搏击技能 jquery easyui中的相关代码如下:用 ...

  4. apk反编译(仅供娱乐)

    第一个文件夹里面放apk,第二个解析classes.dex,第三个查看java代码,下面三个apktool用来解析apk文件, 记得在环境变量中配置apktool,路径为apktool所在路径 1.解 ...

  5. oracle基本语句(第五章、数据库逻辑存储结构管理)

    1.使用SYS用户以SYSDBA身份登录到SQL Plus,使用视图V$TABLESPACE查看表空间信息 SELECT * FROM V$TABLESPACE; 2.查看视图DBA_TABLESPA ...

  6. mysql修改库名

    #!/bin/bash # 假设将sakila数据库名改为new_sakila # MyISAM直接更改数据库目录下的文件即可 mysql -uroot -p123456 -e 'create dat ...

  7. mysql分组排序加序号

    参照https://www.cnblogs.com/CharlieLau/p/6737243.html 一.需求 新加一个Sort 字段,初始值为1,按照parentID分组添加sort值. 根据原数 ...

  8. Python简单雷达图绘制

    import numpy as npimport matplotlib.pyplot as pltimport matplotlibmatplotlib.rcParams['font.family'] ...

  9. BZOJ 4653: [Noi2016]区间 双指针 + 线段树

    只要一堆线段有重叠次数大于等于 $m$ 次的位置,那么一定有解 因为重叠 $m$ 次只需 $m$ 个线断,将那些多余的线断排除掉即可 先将区间按照长度从小到大排序,再用 $two-pointer$ 从 ...

  10. Egret Tween

    最近开始接触Egret,其实也就是为了写一些小的特效 1.egret.Tween.get() ,激活一个对象,对其添加 Tween 动画 2.to() ,将指定对象的属性修改为指定值 egret.Tw ...