Java中的线程Thread方法之---join()
2017-06-24 00:00
453 查看
上一篇我们说到了Thread中的stop方法,这一篇我们再来看一下方法join的使用,那么方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答。
join方法从字面上的意思就是加入到一个线程中,这样就可以很好的进行线程之间的交互运行了,不多说先来看一下代码:
运行代码,貌似永远都看不到a的值是5,而每次都是0,原因很简单的,因为在thread中的run方法中进行a的增值操作,这些可能都是需要时间的,但是此时main线程中的System.out.println方法已经执行了,所以很难看到a的值是5,为了看到a的值是5,我的一个思路就是等thread运行结束之后,我们采取执行System.out.println就可以了,这时候join方法的作用就显现出来的,我们把上面的注释代码删除注释,然后运行,不管运行多少次,输出的结果都是5,从这个例子中我们就可以看到join方法的作用,它能够调节各个线程之间的运行顺序,从而可以实现同步。为了更好的了解join的运行原理我们只有看他的源码了:
[java]
view plain
copy
public final void join() throws InterruptedException {
join(0);
}
我们在跟踪到join(0)方法中:
[java]
view plain
copy
//方法是个同步的,而且会抛出InterruptedException异常
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");
}
//我们可以看到这里使用了while循环做判断的,然后调用wait方法的,所以说join方法的执行是完全通过wait方法实现的
//等待时间为0的时候,就是无限等待,直到线程死亡了(即线程执行完了)
if (millis == 0) {
//如果当前线程还存活的话,就等待
while (isAlive()) {
//调用该线程的join方法的线程拿到锁之后进行等待,直到线程执行结束(这个例子就是main线程)
wait(0);
}
} else {
//如果是等待的特定时间的话
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从代码中我们可以看到join方法是个同步的,这个我们后面会做个例子,然后进入到方法中我们可以看到,有两种情况,一种是等待时间是0的,其实就等同无线等待,直到线程执行结束了,还有一种就是要等待的是一定的时间,原理都是一样的,
看完源码之后我们在看一一个例子:
[java]
view plain
copy
package com.threadjoin.demo;
/**
*
其实Join方法实现是通过wait(小提示:Object 提供的方法)。
当main线程调用t.join时候,main线程会获得线程对象t的锁(wait意味着拿到该对象的锁),
调用该对象的wait(等待时间),直到该对象唤醒main线程,比如退出后。
这就意味着main 线程调用t.join时,
必须能够拿到线程t对象的锁,如果拿不到它是无法wait的,刚开的例子t.join(1000)不是说明了main线程等待1秒,
如果在它等待之前,其他线程获取了t对象的锁,它等待时间可不就是1秒了
* @author weijiang204321
*
*/
public class ThreadJoinTest {
public static void main(String[] args) {
Thread t = new Thread(new RunnableImpl());
new ThreadTest(t).start();
t.start();
try {
t.join(1000);
System.out.println("joinFinish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class RunnableImpl implements Runnable {
@Override
public void run() {
try {
System.out.println("Begin sleep");
Thread.sleep(1000);
System.out.println("End sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadTest extends Thread {
Thread thread;
public ThreadTest(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
holdThreadLock();
}
public void holdThreadLock() {
//用当前的线程当做lock
synchronized (thread) {
System.out.println("getObjectLock");
try {
Thread.sleep(9*1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("ReleaseObjectLock");
}
}
}
在main方法中 通过new ThreadTest(t).start()实例化 ThreadTest 线程对象, 它 通过 synchronized (thread) ,获取线程对象t的锁,并sleep(9*1000)后释放,因为我们上面看到了join方法是个同步的,而且同步锁是当前的线程对象,因为ThreadTest先运行的,首先拿到了线程t对象的锁,所以join方法还没有拿到锁,所以要等待。这就意味着,即使main方法t.join(1000)等待一秒钟,它必须等待ThreadTest 线程释放t锁后才能进入wait方法中,它实际等待时间是9000+1000ms=10s。
join方法从字面上的意思就是加入到一个线程中,这样就可以很好的进行线程之间的交互运行了,不多说先来看一下代码:
package com.threadjoin.demo; public class ThreadJoin { public static int a = 0; public static void main(String[] args){ Thread thread = new Thread(new Runnable(){ @Override public void run(){ for(int i=0;i<5;i++) a++; } }); thread.start(); /*try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); }*/ System.out.println(a); } }
运行代码,貌似永远都看不到a的值是5,而每次都是0,原因很简单的,因为在thread中的run方法中进行a的增值操作,这些可能都是需要时间的,但是此时main线程中的System.out.println方法已经执行了,所以很难看到a的值是5,为了看到a的值是5,我的一个思路就是等thread运行结束之后,我们采取执行System.out.println就可以了,这时候join方法的作用就显现出来的,我们把上面的注释代码删除注释,然后运行,不管运行多少次,输出的结果都是5,从这个例子中我们就可以看到join方法的作用,它能够调节各个线程之间的运行顺序,从而可以实现同步。为了更好的了解join的运行原理我们只有看他的源码了:
[java]
view plain
copy
public final void join() throws InterruptedException {
join(0);
}
我们在跟踪到join(0)方法中:
[java]
view plain
copy
//方法是个同步的,而且会抛出InterruptedException异常
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");
}
//我们可以看到这里使用了while循环做判断的,然后调用wait方法的,所以说join方法的执行是完全通过wait方法实现的
//等待时间为0的时候,就是无限等待,直到线程死亡了(即线程执行完了)
if (millis == 0) {
//如果当前线程还存活的话,就等待
while (isAlive()) {
//调用该线程的join方法的线程拿到锁之后进行等待,直到线程执行结束(这个例子就是main线程)
wait(0);
}
} else {
//如果是等待的特定时间的话
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从代码中我们可以看到join方法是个同步的,这个我们后面会做个例子,然后进入到方法中我们可以看到,有两种情况,一种是等待时间是0的,其实就等同无线等待,直到线程执行结束了,还有一种就是要等待的是一定的时间,原理都是一样的,
看完源码之后我们在看一一个例子:
[java]
view plain
copy
package com.threadjoin.demo;
/**
*
其实Join方法实现是通过wait(小提示:Object 提供的方法)。
当main线程调用t.join时候,main线程会获得线程对象t的锁(wait意味着拿到该对象的锁),
调用该对象的wait(等待时间),直到该对象唤醒main线程,比如退出后。
这就意味着main 线程调用t.join时,
必须能够拿到线程t对象的锁,如果拿不到它是无法wait的,刚开的例子t.join(1000)不是说明了main线程等待1秒,
如果在它等待之前,其他线程获取了t对象的锁,它等待时间可不就是1秒了
* @author weijiang204321
*
*/
public class ThreadJoinTest {
public static void main(String[] args) {
Thread t = new Thread(new RunnableImpl());
new ThreadTest(t).start();
t.start();
try {
t.join(1000);
System.out.println("joinFinish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class RunnableImpl implements Runnable {
@Override
public void run() {
try {
System.out.println("Begin sleep");
Thread.sleep(1000);
System.out.println("End sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadTest extends Thread {
Thread thread;
public ThreadTest(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
holdThreadLock();
}
public void holdThreadLock() {
//用当前的线程当做lock
synchronized (thread) {
System.out.println("getObjectLock");
try {
Thread.sleep(9*1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("ReleaseObjectLock");
}
}
}
在main方法中 通过new ThreadTest(t).start()实例化 ThreadTest 线程对象, 它 通过 synchronized (thread) ,获取线程对象t的锁,并sleep(9*1000)后释放,因为我们上面看到了join方法是个同步的,而且同步锁是当前的线程对象,因为ThreadTest先运行的,首先拿到了线程t对象的锁,所以join方法还没有拿到锁,所以要等待。这就意味着,即使main方法t.join(1000)等待一秒钟,它必须等待ThreadTest 线程释放t锁后才能进入wait方法中,它实际等待时间是9000+1000ms=10s。
相关文章推荐
- 详细介绍了java线程Thread的join()方法
- java Thread 线程的.Join()方法
- Java中的线程Thread方法之---join()
- java进阶 线程池 join用法总结:thread4.join();方法,就表明thread4.join();这个线程受到贵客待遇,直到这个线程执行完,被插入这个方法的载体线程才可以执行。
- Java中的线程Thread方法之---join()
- Java中的线程Thread方法之---stop()
- [Java] Thread 创建线程的第二种方法
- JAVA中创建线程对象的两种方法:继承Thread和实现Runable
- Java Thread Join方法
- 线程Thread join 方法---优先执行
- java 创建线程的三种方法Callable,Runnable,Thread比较及用法
- Java线程中sleep()、wait()和notify()和notifyAll()、yield()、join()等方法的用法和区别
- 【转载】JAVA中线程的两种实现方法-实现Runnable接口和继承Thread类
- [Java] Thread 创建线程的第二种方法
- Java中的线程Thread方法之---suspend()和resume()
- java之Thread线程相关yield()、sleep()、wait()、join()、run和start区别详解
- java线程当中 sleep() join() yield()方法的简单比较以及如何保护共享数据介绍
- java中Thread线程中的 start()和run()方法的区别
- java基础学习__多线程(停止线程,守护线程,join方法)
- java谜题--Thread.join()方法容易忽略的地方