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 
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 


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

其中对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.
     * 

An invocation of this method behaves in exactly the same * way as the invocation * *

* {@linkplain #join(long) join}{@code (0)} *
* @throws InterruptedException * if any thread has interrupted the current thread. The * interrupted status 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.
     *
     * 

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 * interrupted status 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类 

  1. class AThread extends Thread {
        BThread bt;
        public AThread(BThread bt) {
            super("[AThread] Thread");
            this.bt = bt;
        }
        public void run() {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + " start.");
            try {
    // 这里加入了bt线程 
                bt.join();
                System.out.println(threadName + " end.");
            } catch (Exception e) {
                System.out.println("Exception from " + threadName + ".run");
            }
        }
    }
     
    class BThread extends Thread {
        public BThread() {
            super("[BThread] Thread");
        };
        public void run() {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + " start.");
            try {
                for (int i = 0; i < 5; i++) {
                    System.out.println(threadName + " loop at " + i);
                    Thread.sleep(1000);
                }
                System.out.println(threadName + " end.");
            } catch (Exception e) {
                System.out.println("Exception from " + threadName + ".run");
            }
        }
    }
    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();
            } catch (Exception e) {
                System.out.println("Exception from main");
            }
            System.out.println(threadName + " end!"+"时间 :"+System.currentTimeMillis());
        }
    }

    最后结果为
     

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

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.






参考文章:http://www.open-open.com/lib/view/open1371741636171.html




















你可能感兴趣的:(java多线程,java)