并发编程Java学习笔记

Python & Java 多线程Join方法

2017-08-08  本文已影响82人  Alien的小窝

join 是Thread 的方法。

import time, threading

# 假定这是你的银行存款:
balance = 0

def change_it(n):
    # 先存后取,结果应该为0:
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(100000):
        change_it(n)

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)

阻塞当前线程,等待到该线程结束,才开始执行后面语句。
Join之后类似于Java,似乎变成单线程了。

Java 的Join

thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

thread.join(1000); 也可以调用join时候加上一个超时参数,如果目标线程在这段时间到期时候还没有结束的话,join方法总能返回。

join 源码

 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 方法是synchronized 修饰的,且调用对象是thread,所以当main线程调用t.join时,main线程会获得线程对象t的锁(哪个线程调用synchronized方法 哪个线程获得锁,而此处是对象Thread t的对象锁[join是Thread的方法 ])
调用该对象t的wait(等待时间),直到该对象t唤醒main线程 ,比如退出后。

public class Test {
    public static void main(String[] args) {
        
        Thread thread1 = new Thread(){
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                    System.out.println("thread handle 1");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        
        Thread thread2 = new Thread(){
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                    System.out.println("thread handle 2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        
        thread1.start();
        thread2.start();
        
        try {
            thread1.join();
            System.out.println("==============>");
            thread2.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("end");
        
    }
}

为了更清楚的看到结果,可以更改两个线程的Thread休眠时间。

执行结果有3种:

Thread-0
Thread-1
thread handle 1
thread handle 2
==============>
end

Thread-0
Thread-1
thread handle 1
==============>
thread handle 2
end

Thread-0
Thread-1
thread handle 2
thread handle 1
==============>
end

可以看出2个线程同时启动,但是结束的顺序不一定
如 情况一

Thread0.join() start
Thread0首先执行完
Thread0.join() end
输入 =======> 
Thread1.join() start
Thread1 执行完
Thread1.join() end
System.out.println("end")

情况二

Thread0.join() start
Thread1首先执行完
Thread0执行完
Thread0.join() end
输入 =======> 
Thread1.join() start  (isAlive = false 的直接跳过阻塞)
Thread1.join() end
System.out.println("end")

情况三

Thread0.join() start
Thread0首先执行完
Thread1执行完 (2个线程几乎同时执行完至少比Thread0.join()快)
Thread0.join() end
输入 =======> 
Thread1.join() start  (isAlive = false 的直接跳过阻塞)
Thread1.join() end
System.out.println("end")
上一篇 下一篇

猜你喜欢

热点阅读