-
JAVA多线程中join()方法的详细分析
2018-05-06 12:47:53虽然关于讨论线程join()方法的博客已经非常极其特别多了,但是前几天我有一个困惑却没有能够得到详细解释,就是当系统中正在运行多个线程时,join()到底是暂停了哪些线程,大部分博客给的例子看起来都像是t.join()...虽然关于讨论线程join()方法的博客已经非常极其特别多了,但是前几天我有一个困惑却没有能够得到详细解释,就是当系统中正在运行多个线程时,join()到底是暂停了哪些线程,大部分博客给的例子看起来都像是t.join()方法会使所有线程都暂停并等待t的执行完毕。当然,这也是因为我对多线程中的各种方法和同步的概念都理解的不是很透彻。通过看别人的分析和自己的实践之后终于想明白了,详细解释一下希望能帮助到和我有相同困惑的同学。
首先给出结论:t.join()方法只会使主线程(或者说调用t.join()的线程)进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程。
下面则是分析过程。
之前对于join()方法只是了解它能够使得t.join()中的t优先执行,当t执行完后才会执行其他线程。能够使得线程之间的并行执行变成串行执行。
package CSDN; public class TestJoin { public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub ThreadTest t1=new ThreadTest("A"); ThreadTest t2=new ThreadTest("B"); t1.start(); t2.start(); } } class ThreadTest extends Thread { private String name; public ThreadTest(String name){ this.name=name; } public void run(){ for(int i=1;i<=5;i++){ System.out.println(name+"-"+i); } } }
运行结果:
A-1 B-1 B-2 B-3 A-2 B-4 A-3 B-5 A-4 A-5
可以看出A线程和B线程是交替执行的。
而在其中加入join()方法后(后面的代码都略去了ThreadTest类的定义)
package CSDN; public class TestJoin { public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub ThreadTest t1=new ThreadTest("A"); ThreadTest t2=new ThreadTest("B"); t1.start(); t1.join(); t2.start(); } }
运行结果:
A-1 A-2 A-3 A-4 A-5 B-1 B-2 B-3 B-4 B-5
显然,使用t1.join()之后,B线程需要等A线程执行完毕之后才能执行。需要注意的是,t1.join()需要等t1.start()执行之后执行才有效果,此外,如果t1.join()放在t2.start()之后的话,仍然会是交替执行,然而并不是没有效果,这点困扰了我很久,也没在别的博客里看到过。
为了深入理解,我们先看一下join()的源码。
/** * Waits for this thread to die. * * <p> An invocation of this method behaves in exactly the same * way as the invocation * * <blockquote> * {@linkplain #join(long) join}{@code (0)} * </blockquote> * * @throws InterruptedException * if any thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown. */ public final void join() throws InterruptedException { join(0); //join()等同于join(0) } /** * Waits at most {@code millis} milliseconds for this thread to * die. A timeout of {@code 0} means to wait forever. * * <p> This implementation uses a loop of {@code this.wait} calls * conditioned on {@code this.isAlive}. As a thread terminates the * {@code this.notifyAll} method is invoked. It is recommended that * applications not use {@code wait}, {@code notify}, or * {@code notifyAll} on {@code Thread} instances. * * @param millis * the time to wait in milliseconds * * @throws IllegalArgumentException * if the value of {@code millis} is negative * * @throws InterruptedException * if any thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown. */ 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); //join(0)等同于wait(0),即wait无限时间直到被notify } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
可以看出,join()方法的底层是利用wait()方法实现的。可以看出,join方法是一个同步方法,当主线程调用t1.join()方法时,主线程先获得了t1对象的锁,随后进入方法,调用了t1对象的wait()方法,使主线程进入了t1对象的等待池,此时,A线程则还在执行,并且随后的t2.start()还没被执行,因此,B线程也还没开始。等到A线程执行完毕之后,主线程继续执行,走到了t2.start(),B线程才会开始执行。
此外,对于join()的位置和作用的关系,我们可以用下面的例子来分析
package CSDN; public class TestJoin { public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub System.out.println(Thread.currentThread().getName()+" start"); ThreadTest t1=new ThreadTest("A"); ThreadTest t2=new ThreadTest("B"); ThreadTest t3=new ThreadTest("C"); System.out.println("t1start"); t1.start(); System.out.println("t2start"); t2.start(); System.out.println("t3start"); t3.start(); System.out.println(Thread.currentThread().getName()+" end"); } }
运行结果为
main start t1start t1end t2start t2end t3start t3end A-1 A-2 main end C-1 C-2 C-3 C-4 C-5 A-3 B-1 B-2 B-3 B-4 B-5 A-4 A-5
A、B、C和主线程交替运行。加入join()方法后
package CSDN; public class TestJoin { public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub System.out.println(Thread.currentThread().getName()+" start"); ThreadTest t1=new ThreadTest("A"); ThreadTest t2=new ThreadTest("B"); ThreadTest t3=new ThreadTest("C"); System.out.println("t1start"); t1.start(); System.out.println("t1end"); System.out.println("t2start"); t2.start(); System.out.println("t2end"); t1.join(); System.out.println("t3start"); t3.start(); System.out.println("t3end"); System.out.println(Thread.currentThread().getName()+" end"); } }
运行结果:
main start t1start t1end t2start t2end A-1 B-1 A-2 A-3 A-4 A-5 B-2 t3start t3end B-3 main end B-4 B-5 C-1 C-2 C-3 C-4 C-5
多次实验可以看出,主线程在t1.join()方法处停止,并需要等待A线程执行完毕后才会执行t3.start(),然而,并不影响B线程的执行。因此,可以得出结论,t.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程。
PS:join源码中,只会调用wait方法,并没有在结束时调用notify,这是因为线程在die的时候会自动调用自身的notifyAll方法,来释放所有的资源和锁。
-
[Java基础]StringUtils.join()方法与String.join()方法的使用
2018-07-12 11:33:07StringUtils.join()和String.join()用途:将数组或集合以某拼接符拼接到一起形成新的字符串。 1.StringUtils.join()方法: (1)使用前需先引入common-lang3的jar包,可去官网下载:apache官网下载页面 (2)...StringUtils.join()和String.join()用途:将数组或集合以某拼接符拼接到一起形成新的字符串。
1.StringUtils.join()方法:
(1)使用前需先引入common-lang3的jar包,可去官网下载:apache官网下载页面
(2)方法如下图:
(3)基本上此方法需传入2个参数,第一个参数是传入一个任意类型数组或集合,第二个参数是拼接符。
List<String> list = new ArrayList<>(); list.add("Mxy"); list.add("StringUtils"); list.add("join"); String join = StringUtils.join(list,"-");//传入String类型的List集合,使用"-"号拼接 System.out.println(join); String[] s = new String[]{"Yuan","Mxy"};//传入String类型的数组,使用"-"号拼接 String join2 = StringUtils.join(s,"-"); System.out.println(join2);
结果如下:
Mxy-StringUtils-join Yuan-Mxy
2.String.join()方法:String.join()是JDK8新增方法(无需引包)
发现参数为2个,第一个参数为拼接符号,第二个参数为数组和集合
这里和StringUtils.join()有区别,参数顺序不一样,另外,StringUtils.join()可以传入Integer或者其他类型的集合或数组,而String.join()尽可以传入实现charSequence接口类型的集合或数组。
如果是字符串类型的集合或数组推荐使用String.join()。
代码如下:
List<String> list = new ArrayList<>(); list.add("Mxy"); list.add("String"); list.add("join"); String join = String.join("-",list);//传入String类型的List集合,使用"-"号拼接 System.out.println(join); String[] s = new String[]{"Yuan","Mxy"};//传入String类型的数组,使用"-"号拼接 String join2 = String.join("-",s); System.out.println(join2);
结果如下:
Mxy-StringUtils-join Yuan-Mxy
Mxy-StringUtils-joinYuan-Mxy
-
os.path.join()函数用法
2019-02-24 15:04:02python路径拼接os.path.join()函数的用法 os.path.join()函数:连接两个或更多的路径名组件 1.如果各组件名首字母不包含’/’,则函数会自动加上 2.第一个以”/”开头的参数开始拼接,之前的参数全部丢弃,当有...python路径拼接os.path.join()函数的用法
os.path.join()函数:连接两个或更多的路径名组件
1.如果各组件名首字母不包含’/’,则函数会自动加上
2.第一个以”/”开头的参数开始拼接,之前的参数全部丢弃,当有多个时,从最后一个开始
3.如果最后一个组件为空,则生成的路径以一个’/’分隔符结尾
print("2:",os.path.join('/aaaa','/bbbb','/ccccc.txt')) #不良写法习惯
>>>2: /ccccc.txt
print("22:",os.path.join('/aaaa/','bbbb/','ccccc.txt')) #通常可以这样写
>>>22: aaaa/bbb/ccccc.txt
import os Path1 = 'home' Path2 = 'develop' Path3 = 'code' Path10 = Path1 + Path2 + Path3 Path20 = os.path.join(Path1,Path2,Path3) print ('Path10 = ',Path10) print ('Path20 = ',Path20) 输出 Path10 = homedevelopcode Path20 = home\develop\code
>>>print("1:",os.path.join('aaaa','/bbbb','ccccc.txt'))
#以字符串中含有 / 的第一个开始拼接:
1: /bbbb/ccccc.txt
-
python路径拼接os.path.join()函数完全教程
2018-01-28 10:38:54os.path.join()函数用于路径拼接文件路径。 os.path.join()函数中可以传入多个路径: 会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃。 以上一种情况为先。在上一种情况确保情况下,若出现”./”开头...os.path.join()函数用于路径拼接文件路径。
os.path.join()函数中可以传入多个路径:会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃。
以上一种情况为先。在上一种情况确保情况下,若出现”./”开头的参数,会从”./”开头的参数的上一个参数开始拼接。
import os print("1:",os.path.join('aaaa','/bbbb','ccccc.txt')) print("2:",os.path.join('/aaaa','/bbbb','/ccccc.txt')) print("3:",os.path.join('aaaa','./bbb','ccccc.txt'))
输出为
1: /bbbb\ccccc.txt 2: /ccccc.txt 3: aaaa\./bbb\ccccc.txt
-
R语言学习笔记(3)——left_join() right_join() inner_join() full_join()
2020-09-21 03:28:50目录摘要函数介绍inner_join()left_join()right_join()full_join()实例inner_join()left_join()right_join()full_join() 摘要 最近学习了《R数据科学》里的合并连接内容,这里直接用中文的表格来分析一下,可能更好... -
python路径拼接os.path.join()函数
2018-04-21 20:19:52函数:string.join() Python中有join()和os.path.join()两个函数,具体作用如下: str.join(): 连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串 os.path.join(): 将多... -
split().reverse().join()用法
2020-06-11 00:01:01var message = 'Hello Vue....join() :方法也就是把数组中的所有元素以字符串的形式输出 例子: 1.split(): stringObject.split(a,b)这是它的语法: a是必须的 决定个从a开始分割 b不是必须的,可选。该参数可.. -
wait(), notify(), notifyAll(),join(),sleep(),yield()等方法介绍
2019-04-19 15:19:54一.概述 ... wait(), notify(), notifyAll(),join(),sleep(),yield()等方法介绍 2. wait()和notify() 3. wait(long timeout)和notify() 4. wait() 和 notifyAll() 5.wait()和join() 6. 为... -
splice(), reverse()/sort(),join()等函数用法
2019-08-03 11:34:17这三个函数最早在Vue,js 文档中看到使用, split(), reverse(),join() 之前虽说对这三个函数有个了解,但是一连串的使用的时候看的我还是一点蒙蔽,故写下此博客 首先 split();: 该方法可以通过指定起始索引和数据... -
Python中的join()函数
2019-05-07 20:56:55Python中的join()函数 join()是一个字符串方法,它返回被子字符串连接的字符串。 语法: ...string_name.join(iterable) ...string_name:这是被连接的子字符串...参数:The join() method takes join()方法需要可迭... -
split().reverse().join()放一起 好记很多
2019-01-04 19:46:59var message = 'Hello Vue.js!' message.split('').reverse().join('')//"!sj.euV olleH" split() 方法用于把一个字符串分割成字符串数组。...join() 方法用于把数组中的所有元素放入一个字符串。 ... -
Thread类中的方法:join()、sleep()、yield()之间的区别
2018-07-20 11:47:282. Join()方法 3. Sleep() 方法:不会释放锁 4. Yield()方法:线程让步 不会释放锁 1. Thread类中的常用方法简介 首先,先看一下Thread类中的常见方法: 最主要的是区分其中join()、sleep()、yield()的用法... -
ArrayList转换为String的方法汇总(StringBuffer和StringUtils.join())
2020-06-02 12:11:23public String arrayToString() { List<Character> result = new ArrayList<Character>(); result.add('a'); result.add('b'); //['a', 'b'] StringBuffer resultStr = new StringBuffer();// 利用... -
Java多线程系列--join()和yield()和interrupt()理解
2019-08-16 11:12:44join()和yield()和interrupt()理解 -
Go 字符串常用函数。Contains()、Join()、Index()、Repeat()、Replace()、Split()、Trim()、Fields()
2019-03-19 10:01:46demo.go(字符串常用函数): package main import ( "fmt" "strings" ) func main() { // Contains() 字符串是否包含 b := strings.Contains("hello world","llo")... // Join() 将字符串切片进行拼接 sli... -
并发编程之join()和yield()和sleep()区别
2019-03-01 17:12:30join()和yield()和sleep() 一:join() 很多时候,A线程的输出十分依赖B线程的输入,这个时候A线程就必须等待B线程执行完之后再根据线程B的执行结果进行输出。而JDK正提供了 join() 方法来实现这个功能。如下两个join... -
Spark join()和cogroup()区别
2019-04-05 18:41:03官网对join和cogroup解释 示例代码: /** * join(otherDataSet,[numTasks]) * 加入一个RDD,在一个(k,v)和(k,w)类型的dataSet上调用,返回一... def join(): Unit ={ val list1RDD = sc.parallelize(L... -
java join()基本用法与说明解释
2018-11-28 22:03:30join()方法的作用,是等待这个线程结束; 也就是说,t.join()方法阻塞调用此方法的线程(calling thread)进入 TIMED_WAITING 状态,直到线程t完成,此线程再继续; 通常用于在main()主线程内,等待其它线程完成再... -
C++11多线程中的detach()、join()、joinable()
2019-07-19 16:21:02一般来说,我们在主线程中开辟出一些子线程来完成我们的任务,正常情况下,需要在主线程的最后调用join(),用于阻塞主线程,避免主线程先于其他子线程执行完毕,退出,然后导致整个进程的异常. join():阻塞主线程,等待其他... -
join()方法
2018-09-04 12:08:08Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。 语法 join()方法语法: str.join(sequence) 参数 sequence -- 要连接的元素序列。 返回值 返回通过指定字符连接序列中元素后生成... -
Java 的Split()与Join()用法
2019-06-20 09:54:03Join()方法是将数组转换成字符串。 1.join() 方法用于把数组中的所有元素放入一个字符串。 元素是通过指定的分隔符进行分隔的。 指定分隔符方法join("#");其中#可以是任意. 2.与之相反的是split()方法:用于把一... -
StringUtils.join()和String.join()区别
2018-01-28 22:26:16StringUtils.join()和String.join():可用来把字符串数组拼接成整条字符串,效果一样只是用法稍有不同,StringUtils要引入jar包common-lang3, String.join()是JDK8新增方法。 例子如下: -
Python - join() + os.path.join()
2019-06-22 11:03:03【专题:Python - os.path 】 a.join("xxx"):将a字符串插入到"xxx...注意:join()方法使用时,参数中的list必须要求所有内容都为str类型: print("".join([str(i) for i in [1,2,3,4,5]])) >>> a =... -
pandas合并拼接的三种方法-join()、merge()及concat()方法
2019-12-04 11:03:331.join()方法 这个方法通常的使用方式为caller.join(),其中caller为DataFrame类型的数据。先来看join()方法中的参数,具体如下: 参数 参数说明 other 要与caller合并拼接的数据。该参数可以接收三种类型... -
StringUtils.join()方法与String.join()方法的使用
2019-11-12 09:52:481.定义一个数组,将你要用逗号分隔的字符串循环添加到list里面 ...用StringUtils.join()方法进行取出用逗号分隔的字符串,不用处理最后一个逗号 String str = StringUtils.join(list.toArray(), ","); ... -
线程方法join()和sleep()区别
2017-10-31 15:09:18描述:方法join()的作用是使所属的线程对象x正常执行run()方法,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行当前现在z后面的代码。join()方法具有使线程排队运行的作用,有些类似synchronized,与... -
Thread.join()
2019-02-11 21:34:54当前线程A等待thread线程终止之后才能从thread.join()返回。线程Thread除了提供join()方法之外,还提供了join(long millis)和join(long millies,int nanos)两个具备超时特性的方法。这两个超时方法标识,如果线程... -
join()和split()方法
2016-02-03 19:28:301.join()和split()方法 var x; var a=new Array(); a[0]="XHTML"; a[1]="CSS"; a[2]="JavaScript"; alert(a.join()); alert(typeof(a.join)); alert(typeof(a)); join() 方法用于把数组中的所有元素放... -
Python中 os.path.join()与join()
2018-07-10 23:55:361.os.path.join()函数os.path.join(): 是将多个路径组合后返回。用法如下:使用os.path.join()将路径./data/ 和 image1合并。2.join()函数可以将元组、字符串、列表中的元素以指定的字符(分隔符)连接生成一个新的... -
Python str join()方法
2019-01-05 20:03:28Python 字符串方法join() 介绍、使用和注意事项。
-
NFS 实现高可用(DRBD + heartbeat)
-
【布道者】Linux极速入门
-
网易云音乐披露用户数据,90后00后成主力军
-
删除win10自带杀毒软件.iso
-
MySQL 数据库权限管理(用户高级管理和精确访问控制)
-
使用卷积神经网络实现猫狗分类(tensorflow2.3.1,附代码)
-
朱老师c++课程第3部分-3.5STL的其他容器讲解
-
自动化测试Python3+Selenium3+Unittest
-
大数运算模板
-
2021-02-27
-
抛弃FlowLayout吧,RecyclerView结合flexbox简单粗暴实现流式布局
-
MHA 高可用 MySQL 架构与 Altas 读写分离
-
Unity Texture Overview Pro 5.0.7z
-
解决CentOS8使用mysql远程连接时无法链接端口问题
-
牛牛量化策略交易
-
王爽《汇编语言》学习环境使用教程和课后题全答案
-
中台详解(下)——怎么搭建中台
-
下载了一个安装文件,不确定是否安全,怎么办?使用Windows自带工具检测下载文件是否完整
-
shell从入门到精通.docx
-
鸿蒙系统Harmonyos源码架构分析-第1期第2课