您好,欢迎来到暴趣科技网。
搜索
您的当前位置:首页java多线程系列 join java多线程:

java多线程系列 join java多线程:

来源:暴趣科技网


java多线程与单线程相比,最大的优点是在多任务的情况下多线程比单线耗时短,可以并发进行

有时候对于单核计算机,我们也觉得很多任务是并发进行的,主要是因为我们的单核cpu对时间进行分片,对

每个任务都分配了时间片。比如给qq分配3ms给腾讯视频分了3ms等等,虽然我们看任务是并行的,实则是

分时运行的。而多核cpu则可以真正并发,这就是多核cpu执行的优势。

下面有一个简单的程序是对java单线程多线程的比较

public class ConcurrencyTest {
private static final long count = 1000000001;
	
	public static void main(String args[]) throws InterruptedException
	{
		concurrency();
		seria();
	}
	//多线程情况下
	private static void  concurrency() throws InterruptedException
	{	//获取当前系统时间
		long start = System.currentTimeMillis();
		Thread thread = new Thread(new Runnable()
		{
			@Override
			public void run() 
			{
				long a = 0;
				for(int i = 0;i < count;i++)
				{
					a+=5;
				}
			}	
		});
		thread.start();
		long b = 0;
		for(int i = 0;i <count;i++)
		{
			b+=5;
		}
		thread.join();//简单理解为等待线程结束,如果线程没有结束的话时间统计不准确
		long time = System.currentTimeMillis() - start;
		System.out.println("concurrency: " +time +" b: "+ time);
	}
	//顺序执行的情况
	private static void seria()
	{
		long start = System.currentTimeMillis();
				long a = 0;
				for(int i = 0;i < count;i++)
				{
					a+=5;
				}
		long b = 0;
		for(int i = 0;i <count;i++)
		{
			b+=5;
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("concurrency: " +time +" b: "+ time);
	}
}
package java_Join;

public class ConcurrencyTest {
private static final long count = 1000000001;	
	public static void main(String args[]) throws InterruptedException
	{
		concurrency();
		seria();
	}
	//多线程情况下
	private static void  concurrency() throws InterruptedException
	{	//获取当前系统时间
		long start = System.currentTimeMillis();
		Thread thread = new Thread(new Runnable()
		{
			@Override
			public void run() 
			{
				long a = 0;
				for(int i = 0;i < count;i++)
				{
					a+=5;
				}
			}	
		});
		thread.start();
		long b = 0;
		for(int i = 0;i <count;i++)
		{
			b+=5;
		}
		thread.join();//简单理解为等待线程结束,如果线程没有结束的话时间统计不准确
		long time = System.currentTimeMillis() - start;
		System.out.println("concurrency: " +time +" b: "+ time);
	}
	//顺序执行的情况
	private static void seria()
	{
		long start = System.currentTimeMillis();
				long a = 0;
				for(int i = 0;i < count;i++)
				{
					a+=5;
				}
		long b = 0;
		for(int i = 0;i <count;i++)
		{
			b+=5;
		}
		long time = System.currentTimeMillis() - start;
		System.out.println("concurrency: " +time +" b: "+ time);
	}
}


其中执行的任务越大,效果越明显。

其中对join的理解其中有参照

个人简单理解是将该线程加入到主线程,主线程要等待其结束,如果该线程没有结束主线程不能结束

比如,你想喝茶,你要烧水,洗茶具,泡茶,喝茶。烧水与洗茶具没什么关联,你可以分开进行,但

是你喝茶的话必须得每件事都完成,所以烧水这种费时的动作就交由一个线程去做,等洗好茶具等烧

水线程完成,就可以泡茶喝茶了。

一、使用方式。

join是Thread类的一个方法,启动线程后直接调用例如

Thread t = new AThread(); t.start(); t.join();

二、为什么要用join()方法 

在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

三、join方法的作用

join
public final void join() throws InterruptedException Waits for this thread to die. 
Throws: InterruptedException  - if any thread has interrupted the current thread. 
The interrupted status of the current thread is cleared when this exception is thrown.

即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。

四、从源码看join()方法

join()的JDK源码

 /**
     * 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);
    }
 /**
     * 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);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

五、用实例来理解 

写一个简单的例子来看一下join()的用法: 

主要包含三个类

1.TestDemo 类

1.AThread 类 

2.BThread类 

TestDemo 类是主类main线程,主类里面加入了AThread 类的线程,AThread 类又加入了BThread类 

可以看得到进程运行变化。

main start.时间 :1497456321225
//主线程起动,因为调用了at.join(),要等到at结束了,此线程才能向下执行
主线程睡眠2000ms
[BThread] Thread start.时间 :1497456321226[BThread] Thread loop at 0时间 :1497456321226
//睡眠1000ms
[BThread] Thread loop at 1时间 :1497456322230
//睡眠1000ms
[BThread] Thread loop at 2时间 :1497456323231
[AThread] Thread start.
//A程起动,因为调用了bt.join(),要等到bt结束了,此线程才能向下执行
[BThread] Thread loop at 3时间 :1497456324236
[BThread] Thread loop at 4时间 :1497456325241
[BThread] Thread end.时间 :1497456326245
[AThread] Thread end.
// 线程AThread在bt.join();阻塞处开始启动,向下继续执行的结果
main end!
//线程AThread结束,此线程在at.join();阻塞处开始启动,向下继续执行的结果。

修改主方法类:

public class TestDemo {
    public static void main(String[] args) {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " start."+"时间 :"+System.currentTimeMillis());
        BThread bt = new BThread();
        AThread at = new AThread(bt);
        try {
            bt.start();
            Thread.sleep(2000);
            at.start();
            //at.join(); //在此处注释掉对join()的调用
        } catch (Exception e) {
            System.out.println("Exception from main");
        }
        System.out.println(threadName + " end!"+"时间 :"+System.currentTimeMillis());
    }
}
结果为
main start.时间 :1497457025126
 // 主线程起动,因为Thread.sleep(2000),主线程没有马上结束;
[BThread] Thread start.时间 :1497457025128
//线程BThread起动
[BThread] Thread loop at 0时间 :1497457025128
[BThread] Thread loop at 1时间 :1497457026128
main end!时间 :1497457027128
//2000ms后主线程结束,留下AThread,与BThread
[AThread] Thread start.
//2000ms线程at启动,因为调用了bt.join(),等到bt结束了,此线程才向下执行。
[BThread] Thread loop at 2时间 :1497457027128
[BThread] Thread loop at 3时间 :1497457028130
[BThread] Thread loop at 4时间 :1497457029131
[BThread] Thread end.时间 :1497457030137
//线程BThread结束了,线程AThread在bt.join();阻塞处开始启动,向下继续执行的结果
[AThread] Thread end.



参考文章:

             
             




















因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- baoquwan.com 版权所有 湘ICP备2024080961号-7

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务