方法join的使用

在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程往往将早于子线程结束之前结束。这时,如果主线程想等待子线程执行完之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法了。

学习join前的铺垫

package Third;

public class MyThread extends Thread {

    @Override
public void run() {
try {
int secondValue = (int) (Math.random() * 10000);
System.out.println(secondValue);
Thread.sleep(secondValue);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
package Third;

public class Test {

    public static void main(String[] args) {

        MyThread threadTest = new MyThread();
threadTest.start(); // Thread.sleep(?)
System.out.println("我想当threadTest对象执行完毕后我再执行");
System.out.println("但上面代码中的sleep()中的值应该写多少呢?");
System.out.println("答案是:根据不能确定:)");
} }

sleep()多少不能确定

用join()方法来解决

package Third;

public class Test {

    public static void main(String[] args) {
try {
MyThread threadTest = new MyThread();
threadTest.start();
threadTest.join(); System.out.println("我想当threadTest对象执行完毕后我再执行,我做到了");
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

方法join的作用是使所属的线程对象X正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。

方法join具有使线程排队运行的作用,有些类似同步的运行效果。join与synchronized的区别是:join在内部使用wait()方法进行等待,而synchronized关键字使用的是“”对象监视器“”原理做为同步。

方法join与异常

在join过程中,如果当前线程对象被中断,则当前线程出现异常

package Third;

public class ThreadA extends Thread {
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String newString = new String();
Math.random();
}
}
}
package Third;

public class ThreadB extends Thread {

    @Override
public void run() {
try {
ThreadA a = new ThreadA();
a.start();
a.join(); System.out.println("线程B在run end处打印了");
} catch (InterruptedException e) {
System.out.println("线程B在catch处打印了");
e.printStackTrace();
}
} }
package Third;

public class ThreadC extends Thread {

    private ThreadB threadB;

    public ThreadC(ThreadB threadB) {
super();
this.threadB = threadB;
} @Override
public void run() {
threadB.interrupt();
} }

方法join(long)使用

参数是设定等待的时间

package Third;

public class MyThread extends Thread {

    @Override
public void run() {
try {
System.out.println("begin Timer=" + System.currentTimeMillis());
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
package Third;

public class Test {

    public static void main(String[] args) {
try {
MyThread threadTest = new MyThread();
threadTest.start(); threadTest.join(2000);//只等2秒
//Thread.sleep(2000); System.out.println(" end timer=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

package Third;

public class Test {

    public static void main(String[] args) {
try {
MyThread threadTest = new MyThread();
threadTest.start(); //threadTest.join(2000);//只等2秒
Thread.sleep(2000); System.out.println(" end timer=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

方法join(long)与sleep(long)的区别

方法join(long)的功能在内部是使用wait(long)方法来实现的,所以join(long)方法具有释放锁的特点。

从源代码中可以了解到,当执行wait(long)方法后,当前线程的锁被释放,那么其他线程就可以调用此线程中的同步方法了。

而Thread.sleep(long)方法却不释放锁,下面的实验证Thread.sleep(long)不释放锁的特点

package Third;

public class ThreadA extends Thread {

    private ThreadB b;

    public ThreadA(ThreadB b) {
super();
this.b = b;
} @Override
public void run() {
try {
synchronized (b) {
b.start();
Thread.sleep(6000);
// Thread.sleep()不释放锁
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Third;

public class ThreadB extends Thread {

    @Override
public void run() {
try {
System.out.println(" b run begin timer="
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" b run end timer="
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
} synchronized public void bService() {
System.out.println("打印了bService timer=" + System.currentTimeMillis());
} }
package Third;

public class ThreadC extends Thread {

    private ThreadB threadB;

    public ThreadC(ThreadB threadB) {
super();
this.threadB = threadB;
} @Override
public void run() {
threadB.bService();
} }
package Third;

public class Run {

    public static void main(String[] args) {

        try {
ThreadB b = new ThreadB(); ThreadA a = new ThreadA(b);
a.start(); Thread.sleep(1000); ThreadC c = new ThreadC(b);
c.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

下面验证Thread.sleep(long)释放锁的特点

更改上面的ThreadA.java

package Third;

public class ThreadA extends Thread {

    private ThreadB b;

    public ThreadA(ThreadB b) {
super();
this.b = b;
} @Override
public void run() {
try {
synchronized (b) {
b.start();
b.join();// 说明join释放锁了
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String newString = new String();
Math.random();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

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

package Third;

public class ThreadA extends Thread {
private ThreadB b; public ThreadA(ThreadB b) {
super();
this.b = b;
} @Override
public void run() {
try {
synchronized (b) {
System.out.println("begin A ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" end A ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Third;

public class ThreadB extends Thread {
@Override
synchronized public void run() {
try {
System.out.println("begin B ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" end B ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Third;

public class Run1 {
public static void main(String[] args) {
try {
ThreadB b = new ThreadB();
ThreadA a = new ThreadA(b);
a.start();
b.start();
b.join(2000);
System.out.println(" main end "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

方法join()后面的代码提前运行:解释意外

package Third;

public class RunFirst {

    public static void main(String[] args) {
ThreadB b = new ThreadB();
ThreadA a = new ThreadA(b);
a.start();
b.start();
System.out.println(" main end=" + System.currentTimeMillis());
} }

《Java多线程编程核心技术》读后感(十一)的更多相关文章

  1. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

  2. Java多线程编程核心技术---对象及变量的并发访问(二)

    数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...

  3. Java多线程编程核心技术

    Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...

  4. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  5. 《java多线程编程核心技术》(一)使用多线程

    了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...

  6. 《Java 多线程编程核心技术》- 笔记

    作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大 ...

  7. Thread.currentThread()和this的区别——《Java多线程编程核心技术》

    前言:在阅读<Java多线程编程核心技术>过程中,对书中程序代码Thread.currentThread()与this的区别有点混淆,这里记录下来,加深印象与理解. 具体代码如下: pub ...

  8. Java多线程编程核心技术(三)多线程通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

  9. Java多线程编程核心技术(二)对象及变量的并发访问

    本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...

  10. Java多线程编程核心技术(一)Java多线程技能

    1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...

随机推荐

  1. Qt中的通用模板算法QtAlgorithms(qDeleteAll,qBinaryFind,qCountLeadingZeroBits,qPopulationCount,qFill,qSwap,qSort)

    Qt在<QtAlgorithms>头文件中为我们提供了一系列的全局模板方法,这些模板方法主要用于容器操作,比如qDeleteAll().其在Qt中的声明如下: void qDeleteAl ...

  2. Vue:实践学习笔记(5)——Vue-Cli脚手架的使用

    Vue:实践学习笔记(5)——Vue-Cli脚手架的使用 快速开始 项目配置 可视化配置 vue ui 命令配置 vue init webpack vue-demo(项目名) 运行测试 进入vue-d ...

  3. Android Studio第一次启动失败的解决办法

    Android Studio Android 开发环境 由于GFW的问题,安装后第一次启动会在显示Fetching android sdk component information对话框后,提示错误 ...

  4. hadoop —— teragen & terasort

    这两个类所在目录: hadoop-examples-0.20.2-cdh3u6.jar 中: 代码: TeraGen.java: /** * Licensed to the Apache Softwa ...

  5. nginx+keepalived简单双机主从热备

    双机主从热备概述 可以两台机子互为热备,平时各自负责各自的服务.在做上线更新的时候,关闭一台服务器的tomcat后,nginx自动把流量切换到另外一台服务的后备机子上,从而实现无痛更新,保持服务的持续 ...

  6. matlab之flipud()函数

    此函数实现矩阵的上下翻转.fliplw()实现左右旋转. 举例: a =[1 2;3 4;5 6] flipud(a)的结果: 5 6 3 4 1 2 fliplr(a)的结果: 2 1 4 3 6 ...

  7. 作业:xml练习1

    作业:使用xml描述下表中的学生成绩信息,XML文件存为scores.xml. 1.打开eclipse软件. 2.file-new-java project,输入project name:201811 ...

  8. RQNOJ 57 找啊找啊找GF:01背包

    题目链接:https://www.rqnoj.cn/problem/57 题意: sqybi在七夕这天太无聊了,所以他想去给自己找GF. 总共有n个MM. 搞定第i个MM要花费rmb[i]块大洋.rp ...

  9. css(3)

    行内元素和块内元素可以通过定义display的属性值进行相互转换. 想要叫ul中的li实现横向显示可以在li中加入布局"float:left": 如: /*这个用于控制单个图片区域 ...

  10. 分享知识-快乐自己:Oracle SQL语法汇总

    --删除重复值-保留重复值最大的编号 delete from emp where rowid in( select rowid from emp where rowid not in( select ...