您的位置:首页 > 编程语言 > Java开发

Java并发05:Thread的基本方法(2)-join方法-线程插队

2018-03-12 12:53 711 查看
[超级链接:Java并发学习系列-绪论]

本章主要对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()方法,达到了预期效果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息