8.Thread的join方法
1.Thread类的join方法表示:当前线程执行结束再执行其它线程!在Thread类中有三个重载的方法分别是:
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;
}
}
}
public final synchronized void join(long millis, int nanos)
throws InterruptedException { if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
} if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
} if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
} join(millis);
}
public final void join() throws InterruptedException {
join(0);
}
如上就是Thread类的3个重载方法!
大家注意一下:上面标记为红色的小红框的英文解释!以及无参的join方法,实际上调用的还是上面这个方法,如下源码所示:
如下Demo演示:
public class JoinDemo{ public static int a = 0; public static void main(String[] args) throws Exception {
Thread t = new Thread(){
@Override
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
}
} };
t.start();
System.out.println(a);
}
}
请 问程序的输出结果是5吗?答案是:有可能。其实你很难遇到输出5的时候,通常情况下都不是5。当然这也和机器有严重的关系。为什么呢?我的解释是当主线程 main方法执行System.out.println(a);这条语句时,线程还没有真正开始运行,或许正在为它分配资源准备运行。因为为线程分配资源需要时间,而main方法执行完t.start()方法后继续往下执行System.out.println(a);,这个时候得到的结果是a还没有被 改变的值0 。怎样才能让输出结果为5!其实很简单,join() 方法提供了这种功能。join() 方法,它能够使调用该方法的线程在此之前执行完毕。所以代码加入了join方法之后,代码如下所示:
public class JoinDemo{
public static int a = 0;
public static void main(String[] args) throws Exception {
Thread t = new Thread(){
@Override
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
}
} };
t.start();
t.join();//加入join方法
System.out.println(a);
}
}
为 了证明如果不使用t.join()方法,主线程main方法的System.out.println(a);语句将抢先执行,我们可以在main方法中加入一个循环,这个循环用来延长main方法执行的时间,循环次数将严重取决于机器性能。如果循环次数得当,我们也可以看到a的输出结果是5。
public class JoinDemo{
public static int a = 0;
public static void main(String[] args) throws Exception {
Thread t = new Thread(){
@Override
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
System.out.println("a的值:"+a);
}
} };
t.start();
for (int i=0; i<300; i++) {
System.out.println(i);
}
System.out.println("静态变量的值为:"+a);
}
}
而使用了join方法之后,a的值就一直是5,但是这里需要注意的是:join方法是位于start方法之后的!
public class JoinDemo{
public static int a = 0;
public static void main(String[] args) throws Exception {
Thread t = new Thread(){
@Override
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
System.out.println("a的值:"+a);
}
} };
t.start();
//join方法位于start方法之后!
t.join();
for (int i=0; i<300; i++) {
System.out.println(i);
}
System.out.println("静态变量的值为:"+a);
}
}
如下所示:
package com.bawei.multithread; public class JoinDemo{
public static int a = 0;
public static void main(String[] args) throws Exception {
Thread t = new Thread(new RunnableImpl());
t.start();
try {
t.join(100);
System.out.println("joinFinish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} class RunnableImpl implements Runnable {
public void run() {
try {
System.out.println("Begin sleep");
Thread.sleep(500);
System.out.println("End sleep");
} catch (InterruptedException e) {
e.printStackTrace();
} }
}
代码执行结果:
Begin sleep
joinFinish
End sleep
结果永远是这个,也就是说当我们为join方法指定了参数了的话,就表示main线程最多会等待这个t线程100毫秒,如果t线程100毫秒都还没执行完,那我也就不管了,我就去不等了,先去干我自己(main线程)的事了!
但是如果我们将t线程等待的时间该为1000,我们在运行如下代码:
package com.bawei.multithread; public class JoinDemo{
public static int a = 0;
public static void main(String[] args) throws Exception {
Thread t = new Thread(new RunnableImpl());
t.start();
try {
t.join(1000);
System.out.println("joinFinish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} class RunnableImpl implements Runnable {
public void run() {
try {
System.out.println("Begin sleep");
Thread.sleep(500);
System.out.println("End sleep");
} catch (InterruptedException e) {
e.printStackTrace();
} }
}
此时就会看到代码的运行结果如下所示:
Begin sleep
End sleep
joinFinish
如下给大家演示个好玩的东西:
public class JoinDemo{ public static void main(String[] args) throws Exception {
Thread.currentThread().join();
}
}
虽然上面就这简简单单的几行代码,但是这个代码就是不会停止,为什么呢?
这是因为main线程一运行,它就执行main方法中的代码:等待自己结束,但是自己有没有结束呢?没有,它也在干事情,就是:在等待自己结束,由于它永远等待不了自己结束,所以这个main线程也就永远不会退出,会一直运行下去!
如下我们可以模拟去多台服务器上采集数据:给每台服务器开一个线程,然后通过多个线程去各个机子上采集数据,如下所示:
//采集数据的线程Runnable【执行单元】
class CaptureRunnable implements Runnable{
//机器名:标识采集的哪个机器上的数据!
private String machineName;
//花费时间
private long spendTime;
//构造函数
public CaptureRunnable(String machineName,long spendTime) {
this.machineName=machineName;
this.spendTime = spendTime;
} @Override
public void run() {
//do the really capture data
try {
Thread.sleep(spendTime);
System.out.println(machineName+" completed capture data and successfully!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getResult(){
return machineName+" finish.";
} }
上面是线程执行单元类,我们开辟几个线程,去调用这个线程执行单元,收集数据:
public class ThreadJoin3 {
public static void main(String[] args) {
long startTimestamp = System.currentTimeMillis(); Thread t1 =new Thread(new CaptureRunnable("M1", 10000L));
Thread t2 =new Thread(new CaptureRunnable("M1", 50000L));
Thread t3 =new Thread(new CaptureRunnable("M1", 30000L));
t1.start();
t2.start();
t3.start(); long endTimestamp = System.currentTimeMillis();
System.out.printf("save data begin timestamp: %s, end timestamp is: %s",startTimestamp,endTimestamp);
}
}
如果是直接这样写的话,大家运行一下就可以看到:线程1【t1】,线程2【t2】,线程3【t3】实际上还没结束呢,但是save data begin timestamp: 1501562292242, end timestamp is ...这句话就已经打印出来了,而且这句话还是提示人家数据采集已经结束了,这样貌似真的不好哎!那怎么办呢?各个线程结束的时间也不是统一的,那这到底怎么解决呢?通过线程对象.join()方法这样就可以将这个解决了,在所有线程采集完毕数据之后,我们再保存数据,保存的是最后那个线程采集数据结束的时间!代码如下所示:
package com.bawei.multithread; public class ThreadJoin3 {
public static void main(String[] args) {
try {
long startTimestamp = System.currentTimeMillis(); Thread t1 =new Thread(new CaptureRunnable("M1", 10000L));
Thread t2 =new Thread(new CaptureRunnable("M1", 50000L));
Thread t3 =new Thread(new CaptureRunnable("M1", 30000L));
t1.start();
t2.start();
t3.start(); t1.join();
t2.join();
t3.join(); long endTimestamp = System.currentTimeMillis();
System.out.printf("save data begin timestamp: %s, end timestamp is: %s",startTimestamp,endTimestamp);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
8.Thread的join方法的更多相关文章
- Thread线程join方法自我理解
Thread线程join方法自我理解 thread.join():等待thread线程运行终止,指的是main-thread(main线程)必须等待thread线程运行结束,才能继续thread.jo ...
- Thread 的join方法
package com.cn.test.thread; public class TestJoin extends Thread{ private String name; public TestJo ...
- 浅析Thread的join() 方法
Thread中的 join() 方法在实际开发过程中可能用的不是很多,但是在面试中作为考察基本功知识的扎实与否,经常会被用到.因此,对于 Thread 的 join() 方法进行了一定的研究. 常见的 ...
- python thread的join方法解释
python的Thread类中提供了join()方法,使得一个线程可以等待另一个线程执行结束后再继续运行.这个方法还可以设定一个timeout参数,避免无休止的等待.因为两个线程顺序完成,看起来象一个 ...
- java线程基础巩固---分析Thread的join方法详细介绍,结合一个典型案例
关于Thread中的join方法貌似在实际多线程编程当中没怎么用过,在当初学j2se的时候倒时去学习过它的用法,不过现在早已经忘得差不多啦,所以对它再复习复习下. 首先先观察下JDK对它的介绍: 其实 ...
- Thread的join方法
一个线程在执行的过程中,可能调用另一个线程,前者可以称为调用线程,后者成为被调用线程. Thread.Join方法的使用场景:调用线程挂起,等待被调用线程执行完毕后,继续执行. 如下案列: 当NewT ...
- Thread中join()方法进行介绍
http://www.cnblogs.com/skywang12345/p/3479275.html https://blog.csdn.net/dabing69221/article/details ...
- 浅谈Java多线程中的join方法
先上代码 新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String ...
- Java多线程中的join方法
新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String name ...
随机推荐
- git bash 命名
git log -p -2 我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新. git diff HEAD git clean -df 恢复到最后一次提交的改动: gi ...
- <笔记>Effective Objective-C 2.0 编写高质量iOS与
1. 内存管理-引用计数 2. 非对象类型 int float double char 3.运行时--编译器(编译时)函数调用 4.@class 缩短编译时间,降低依赖,耦合 5.使用字面量而不是 ...
- 转:AOP与JAVA动态代理
原文链接:AOP与JAVA动态代理 1.AOP的各种实现 AOP就是面向切面编程,我们可以从以下几个层面来实现AOP 在编译期修改源代码 在运行期字节码加载前修改字节码 在运行期字节码加载后动态创建代 ...
- 转:环绕通知返回值 object 类型
遇到 AOP 环绕通知报错 “return value from advice does not match primitive return type for: public boolean” 百 ...
- 图->存储结构->十字链表
文字描述 十字链表是有向图的另一种链式存储结构. 在十字链表中,对应于有向图中每一条弧有一个结点,对应于每个顶点也有一个结点.这些结点的结构如下所示: 在弧结点中有5个域: 尾域tailvex和头域h ...
- 【PyQt5-Qt Designer】PyQt5+pyecharts 实现GUI界面的数据可视化展示
先用纯Python代码写一个简单的小案例: from PyQt5.QtCore import QUrl from PyQt5.QtWidgets import QApplication,QWidget ...
- MySQL InnoDB加锁超时回滚机制(转)
add by zhj: 看来我对MySQL的理解还有待深入,水还是挺深的啊,MySQL给记录加锁时,可以通过innodb_lock_wait_timeout参数设置超时时间, 如果加锁等待超过这个时间 ...
- oracle用户被锁
使用PLSQL客户端:1.用管理员账户登录PLSQL Developer(登录名可以为system,选择类型的时候把Normal修改为Sysdba).2.左侧选择My Objects,查看Users文 ...
- 2018天猫双11各类目品牌成交额top10排行榜
2018天猫双11总成交额213,550,497,011元,你知道各类目品牌成交额排行吗?一起来看看吧,赶紧收藏,以后就知道要怎么买了! 相关阅读: 2018天猫双11各类目品牌成交额top10排行榜 ...
- 理解Spark里的闭包
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/rlnLo2pNEfx9c/article/details/80650309 闭包的概念例如以下图: ...