Java并发05:Thread的基本方法(2)-join方法-线程插队
2018-03-12 12:53
711 查看
[超级链接:Java并发学习系列-绪论]
本章主要对Java中Thread类的基本方法进行学习。
Thread.sleep(long):强制线程睡眠一段时间。
Thread.activeCount():获取当前程序中存活的线程数。
thread.start():启动一个线程。
Thread.currentThread():获取当前正在运行的线程。
thread.getThreadGroup():获取线程所在线程组。
thread.getName():获取线程的名字。
thread.getPriority():获取线程的优先级。
thread.setName(name):设置线程的名字。
thread.setPriority(priority):设置线程的优先级。
thread.isAlive():判断线程是否还存活着。
thread.isDaemon():判断线程是否是守护线程。
thread.setDaemon(true):将指定线程设置为守护线程。
thread.join():在当前线程中加入指定线程,使得这个指定线程等待当前线程,并在当前线程结束前结束。
thread.yield():使得当前线程退让出CPU资源,把CPU调度机会分配给同样线程优先级的线程。
thread.interrupt():使得指定线程中断阻塞状态,并将阻塞标志位置为true。
object.wai()、object.notify()、object.notifyAll():Object类提供的线程等待和线程唤醒方法。
为了便于阅读,将以上所有方法,放在5篇文章中进行学习。
本章主要学习绿色字体标记的方法,其他方法请参加其他章节。
join()方法的作用:Waits for this thread to die.即:等待这个线程结束。
举例说明:
程序中有两个线程:[线程A] = threadA、[线程B]=threadB
在[线程A]的run()方法中,调用了threadB.join()
则[线程A]会在此段代码出,暂停后续代码的调用,等待[线程B]执行结束。
[线程B]执行结束之后,[线程A]才会继续执行后续的未完代码。
关于join()方法更形象的说法:线程插队。
join()方法常用来保证:确保能够完整的获取到插队线程的处理结果。
线程2会对共享变量config进行赋值。
线程1会读取共享变量config。
我们期望线程1能够读取到被线程2赋值之后的变量config。
结果:
分析:
线程1执行时间比线程2更短,所以导致:线程1执行完了,线程2还没来得及对配置config进行赋值。这不是我们想要的结果。
结果:
分析:
在线程1的执行过程中,线程2通过join()加入。
这时,线程1不会再继续执行后续代码,而是等待线程2执行结束。
当线程2执行结束后,线程1继续执行未执行完的代码。
通过join()方法,达到了预期效果。
本章主要对Java中Thread类的基本方法进行学习。
1.序言
Thread类作为线程的基类,提供了一系列方法,主要有:Thread.sleep(long):强制线程睡眠一段时间。
Thread.activeCount():获取当前程序中存活的线程数。
thread.start():启动一个线程。
Thread.currentThread():获取当前正在运行的线程。
thread.getThreadGroup():获取线程所在线程组。
thread.getName():获取线程的名字。
thread.getPriority():获取线程的优先级。
thread.setName(name):设置线程的名字。
thread.setPriority(priority):设置线程的优先级。
thread.isAlive():判断线程是否还存活着。
thread.isDaemon():判断线程是否是守护线程。
thread.setDaemon(true):将指定线程设置为守护线程。
thread.join():在当前线程中加入指定线程,使得这个指定线程等待当前线程,并在当前线程结束前结束。
thread.yield():使得当前线程退让出CPU资源,把CPU调度机会分配给同样线程优先级的线程。
thread.interrupt():使得指定线程中断阻塞状态,并将阻塞标志位置为true。
object.wai()、object.notify()、object.notifyAll():Object类提供的线程等待和线程唤醒方法。
为了便于阅读,将以上所有方法,放在5篇文章中进行学习。
本章主要学习绿色字体标记的方法,其他方法请参加其他章节。
2.join()方法的理解
先来看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()方法的作用:Waits for this thread to die.即:等待这个线程结束。
举例说明:
程序中有两个线程:[线程A] = threadA、[线程B]=threadB
在[线程A]的run()方法中,调用了threadB.join()
则[线程A]会在此段代码出,暂停后续代码的调用,等待[线程B]执行结束。
[线程B]执行结束之后,[线程A]才会继续执行后续的未完代码。
关于join()方法更形象的说法:线程插队。
join()方法常用来保证:确保能够完整的获取到插队线程的处理结果。
3.实例代码与结果
3.1.示例场景
程序中有两个线程1和2,线程1独立运行需要100毫秒,线程2独立运行需要200毫秒。线程2会对共享变量config进行赋值。
线程1会读取共享变量config。
我们期望线程1能够读取到被线程2赋值之后的变量config。
3.2.不用join()
代码:/** * <p>java线程基本方法:join</p> * * @author hanchao 2018/3/11 16:03 **/ public class ThreadJoinDemo { private static final Logger LOGGER = Logger.getLogger(ThreadJoinDemo.class); //线程间的共享资源 private static String config = "配置未被初始化."; /** * <p>join:让当前线程等待指定的线程结束</p> * * @author hanchao 2018/3/11 16:04 **/ public static void main(String[] args) throws InterruptedException { //不加join LOGGER.info("==========不使用t.join()方法=========="); new Thread(() -> { LOGGER.info("[线程1]开始运行..."); Thread otherThread = new Thread(() -> { LOGGER.info("[线程2]开始运行..."); try { Thread.sleep(200);//线程2运行200毫秒 config = "配置已被[线程2]初始化."; } catch (InterruptedException e) { e.printStackTrace(); } LOGGER.info("[线程2]运行结束"); }); //启动线程2 otherThread.start(); try { Thread.sleep(100);//线程1运行100毫秒 } catch (InterruptedException e) { e.printStackTrace(); } LOGGER.info("[线程1]获取的配置为:" + config); LOGGER.info("[线程1]运行结束"); }).start();//启动线程1 } }
结果:
2018-03-12 12:40:24 INFO ThreadJoinDemo:22 - ==========不使用t.join()方法========== 2018-03-12 12:40:24 INFO ThreadJoinDemo:24 - [线程1]开始运行... 2018-03-12 12:40:24 INFO ThreadJoinDemo:26 - [线程2]开始运行... 2018-03-12 12:40:24 INFO ThreadJoinDemo:42 - [线程1]获取的配置为:配置未被初始化. 2018-03-12 12:40:24 INFO ThreadJoinDemo:43 - [线程1]运行结束 2018-03-12 12:40:24 INFO ThreadJoinDemo:33 - [线程2]运行结束
分析:
线程1执行时间比线程2更短,所以导致:线程1执行完了,线程2还没来得及对配置config进行赋值。这不是我们想要的结果。
3.3.添加join()
代码:/** * <p>java线程基本方法:join</p> * * @author hanchao 2018/3/11 16:03 **/ public class ThreadJoinDemo { private static final Logger LOGGER = Logger.getLogger(ThreadJoinDemo.class); //线程间的共享资源 private static String config = "配置未被初始化."; /** * <p>join:让当前线程等待指定的线程结束</p> * * @author hanchao 2018/3/11 16:04 **/ public static void main(String[] args) throws InterruptedException { //使用t.join()方法 Thread.sleep(1000);//等待线程1和线程2都有运行完 System.out.println(); LOGGER.info("==========使用t.join()方法=========="); new Thread(() -> { LOGGER.info("[线程11]开始运行..."); Thread otherThread = new Thread(() -> { LOGGER.info("[线程22]开始运行..."); try { Thread.sleep(200);//线程22运行200毫秒 config = "配置已被[线程22]初始化."; } catch (InterruptedException e) { e.printStackTrace(); } LOGGER.info("[线程22]运行结束"); }); otherThread.start();//启动线程22 try { //在线程11中,加入线程22-->需要等到线程22结束之后才能结束线程11 otherThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } LOGGER.info("[线程11]等待[线程22]结束"); try { Thread.sleep(100);//线程11运行100毫秒 } catch (InterruptedException e) { e.printStackTrace(); } LOGGER.info("[线程1]获取的配置为:" + config); LOGGER.info("[线程11]运行结束"); }).start();//启动线程11 } }
结果:
2018-03-12 12:40:25 INFO ThreadJoinDemo:49 - ==========使用t.join()方法========== 2018-03-12 12:40:25 INFO ThreadJoinDemo:51 - [线程11]开始运行... 2018-03-12 12:40:25 INFO ThreadJoinDemo:53 - [线程22]开始运行... 2018-03-12 12:40:25 INFO ThreadJoinDemo:60 - [线程22]运行结束 2018-03-12 12:40:25 INFO ThreadJoinDemo:69 - [线程11]等待[线程22]结束 2018-03-12 12:40:25 INFO ThreadJoinDemo:75 - [线程1]获取的配置为:配置已被[线程22]初始化. 2018-03-12 12:40:25 INFO ThreadJoinDemo:76 - [线程11]运行结束
分析:
在线程1的执行过程中,线程2通过join()加入。
这时,线程1不会再继续执行后续代码,而是等待线程2执行结束。
当线程2执行结束后,线程1继续执行未执行完的代码。
通过join()方法,达到了预期效果。
相关文章推荐
- Java并发08:Thread的基本方法(5)-interrupt()、isInterrupted()
- Java 多线程CountDownLatch、CyclicBarrier、Thread.join方法基本用法
- Java并发04:Thread的基本方法(1)-Name、ThreadGroup、activeCount、isAlive、守护线程等
- Java并发09:Thread的基本方法(6)-线程优先级priority相关说明与操作
- Java并发06:Thread的基本方法(3)-yield方法的分析与实例说明
- Java中CountDownLatch、CyclicBarrier、Thread.join方法基本应用
- Java并发07:Thread的基本方法(4)-Thread.sleep()、Object.wait()、notify()和notifyAll()
- Java并发的四种口味:Thread、Executor、ForkJoin、Actor
- JAVA 线程的两种基本实现方法(继承Thread类和实现Runnable接口)
- java基本教程之join方法详解 java多线程教程
- Java Thread&Concurrency(1): 深入理解Fork-Join并发执行框架
- Java中的线程Thread方法之---join()
- Java并发之 CAS + Thread.join / CountDownLatch 方式实现线程安全
- java Thread的join()方法
- Java多线程 之 Thread子类 join方法(五)
- JAVA THREAD.JOIN方法详解
- Java 线程与并发研究系列三(join()方法使用)
- Java之Thread的join方法实例
- Java并发的四种风味:Thread、Executor、ForkJoin和Actor
- Java并发学习笔记(13)线程之间的协作(Object.wait(),notifu(),notifyAll() Thread.join())