join的简单总结
BAT面试题:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。
一、作用
Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。具体看代码:
public class JoinTest {
public static void main(String [] args) throws InterruptedException {
ThreadJoinTest t1 = new ThreadJoinTest("小明");
ThreadJoinTest t2 = new ThreadJoinTest("小东");
t1.start();
/**join的意思是使得放弃当前线程的执行,并返回对应的线程,例如下面代码的意思就是:
程序在main线程中调用t1线程的join方法,则main线程放弃cpu控制权,并返回t1线程继续执行直到线程t1执行完毕
所以结果是t1线程执行完后,才到主线程执行,相当于在main线程中同步t1线程,t1执行完了,main线程才有执行的机会
*/
t1.join();
t2.start();
}
}
class ThreadJoinTest extends Thread{
public ThreadJoinTest(String name){
super(name);
}
@Override
public void run(){
for(int i=;i<;i++){
System.out.println(this.getName() + ":" + i);
}
}
}
上面程序结果是先打印完小明线程,在打印小东线程;
上面注释也大概说明了join方法的作用:在A线程中调用了B线程的join()方法时,表示只有当B线程执行完毕时,A线程才能继续执行。注意,这里调用的join方法是没有传参的,join方法其实也可以传递一个参数给它的,具体看下面的简单例子:
public class JoinTest {
public static void main(String [] args) throws InterruptedException {
ThreadJoinTest t1 = new ThreadJoinTest("小明");
ThreadJoinTest t2 = new ThreadJoinTest("小东");
t1.start();
/**join方法可以传递参数,join(10)表示main线程会等待t1线程10毫秒,10毫秒过去后,
* main线程和t1线程之间执行顺序由串行执行变为普通的并行执行
*/
t1.join();
t2.start();
}
}
class ThreadJoinTest extends Thread{
public ThreadJoinTest(String name){
super(name);
}
@Override
public void run(){
for(int i=;i<;i++){
System.out.println(this.getName() + ":" + i);
}
}
}
上面代码结果是:程序执行前面10毫秒内打印的都是小明线程,10毫秒后,小明和小东程序交替打印。
所以,join方法中如果传入参数,则表示这样的意思:如果A线程中掉用B线程的join(10),则表示A线程会等待B线程执行10毫秒,10毫秒过后,A、B线程并行执行。需要注意的是,jdk规定,join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕,即join(0)等价于join()。
二、join与start调用顺序问题
上面的讨论大概知道了join的作用了,那么,如果 join在start前调用,会出现什么后果呢?先看下面的测试结果
public class JoinTest {
public static void main(String [] args) throws InterruptedException {
ThreadJoinTest t1 = new ThreadJoinTest("小明");
ThreadJoinTest t2 = new ThreadJoinTest("小东");
/**join方法可以在start方法前调用时,并不能起到同步的作用
*/
t1.join();
t1.start();
//Thread.yield();
t2.start();
}
}
class ThreadJoinTest extends Thread{
public ThreadJoinTest(String name){
super(name);
}
@Override
public void run(){
for(int i=;i<;i++){
System.out.println(this.getName() + ":" + i);
}
}
}
上面代码执行结果是:小明和小东线程交替打印。
所以得到以下结论:join方法必须在线程start方法调用之后调用才有意义。这个也很容易理解:如果一个线程都没有start,那它也就无法同步了。
三、join方法实现原理
有了上面的例子,我们大概知道join方法的作用了,那么,join方法实现的原理是什么呢?
其实,join方法是通过调用线程的wait方法来达到同步的目的的。例如,A线程中调用了B线程的join方法,则相当于A线程调用了B线程的wait方法,在调用了B线程的wait方法后,A线程就会进入阻塞状态,具体看下面的源码:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = ; if (millis < ) {
throw new IllegalArgumentException("timeout value is negative");
} if (millis == ) {
while (isAlive()) {
wait();
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= ) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从源码中可以看到:join方法的原理就是调用相应线程的wait方法进行等待操作的,例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll方法唤醒A线程,从而达到同步的目的。
join的简单总结的更多相关文章
- java 线程方法join的简单总结
虽然关于讨论线程join方法的博客已经很多了,不过个人感觉挺多都讨论得不够全面,所以我觉得有必要对其进行一个全面的总结. 一.作用 Thread类中的join方法的主要作用就是同步,它可以使得线程之间 ...
- Java并发编程:Java Thread方法join的简单总结
虽然关于讨论线程join方法的博客已经很多了,不过个人感觉挺多都讨论得不够全面,所以我觉得有必要对其进行一个全面的总结. 一.作用 Thread类中的join方法的主要作用就是同步,它可以使得线程之间 ...
- 左查询left join on简单总结
应用场景分析:(个人观点,欢迎小祖宗们指正补充) 适合存在父子关系的单表,以及多表的查询 话不多说上代码 代码:mapper里的sql 表名字段什么的本来是单独集中配置的,现在还原到sql中了 & ...
- 记住left join最简单的方式(转)
表aaid adate1 a12 a23 a3表bbid bdate1 b12 b24 b4 select * from a left join b on a.ai ...
- os模块os.walk() 方法和os.path.join()的简单使用
os.walk: http://www.runoob.com/python/os-walk.html os.path.join: https://blog.csdn.net/zmdzbzbhs ...
- MapReduce 实现数据join操作
前段时间有一个业务需求,要在外网商品(TOPB2C)信息中加入 联营自营 识别的字段.但存在的一个问题是,商品信息 和 自营联营标示数据是 两份数据:商品信息较大,是存放在hbase中.他们之前唯一的 ...
- 《java.util.concurrent 包源码阅读》26 Fork/Join框架之Join
接下来看看调用ForkJoinTask的join方法都发生了什么: public final V join() { // doJoin方法返回该任务的状态,状态值有三种: // NORMAL, CAN ...
- SQL的各种连接Join详解
SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段. 最常见的 JOIN 类型:SQL INNER JOIN(简单的 JOIN).SQL LEFT JOIN.SQL ...
- 【SQL】【Join基础】了解sql中的join用法,看这一篇就够了
转自: https://www.cnblogs.com/reaptomorrow-flydream/p/8145610.html SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之 ...
随机推荐
- [Swift]LeetCode32. 最长有效括号 | Longest Valid Parentheses
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
- [Swift]LeetCode323. 无向图中的连通区域的个数 $ Number of Connected Components in an Undirected Graph
Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...
- [SQL]LeetCode626. 换座位 | Exchange Seats
SQL架构 Create table If Not Exists seat(id )) Truncate table seat insert into seat (id, student) value ...
- 一个简单IP防刷工具类, x秒内最多允许y次单ip操作
IP防刷,也就是在短时间内有大量相同ip的请求,可能是恶意的,也可能是超出业务范围的.总之,我们需要杜绝短时间内大量请求的问题,怎么处理? 其实这个问题,真的是太常见和太简单了,但是真正来做的时候,可 ...
- restful风格的API
在说restful风格的API之前,我们要先了解什么是rest.什么是restful.最后才是restful风格的API! PS(REST:是一组架构约束条件和原则,REST是Roy Thomes F ...
- Python爬虫入门教程 32-100 B站博人传评论数据抓取 scrapy
1. B站博人传评论数据爬取简介 今天想了半天不知道抓啥,去B站看跳舞的小姐姐,忽然看到了评论,那就抓取一下B站的评论数据,视频动画那么多,也不知道抓取哪个,选了一个博人传跟火影相关的,抓取看看.网址 ...
- C++版- Leetcode 3. Longest Substring Without Repeating Characters解题报告
Leetcode 3. Longest Substring Without Repeating Characters 提交网址: https://leetcode.com/problems/longe ...
- Educational Codeforces Round 48 (Rated for Div. 2)——A. Death Note ##
A. Death Note time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- PE知识复习之PE文件空白区添加代码
PE知识复习之PE文件空白区添加代码 一丶简介 根据上面所讲PE知识.我们已经可以实现我们的一点手段了.比如PE的入口点位置.改为我们的入口位置.并且填写我们的代码.这个就是空白区添加代码. 我们也可 ...
- Docker最全教程——从理论到实战(六)
托管到腾讯云容器服务 托管到腾讯云容器服务,我们的公众号“magiccodes”已经发布了相关的录屏教程,大家可以结合本篇教程一起查阅. 自建还是托管? 在开始之前,我们先来讨论一个问题——是自建 ...