通过Thread.join()和CountDownLatch来实现进程同步

来源:互联网 发布:淘宝助理上传宝贝教程 编辑:程序博客网 时间:2024/05/22 15:38

1.Thread.join()

如果在一个进程,如main中调用另一个thread的join()函数会导致main函数阻塞,直至thread执行完毕。

public class JoinTest {public static void main(String[] args) {System.out.println("main starts.");Thread thread = new Thread(new Runnable() {public void run() {for(int i = 0;i < 5;i++){try {System.out.println("thread" + i + " starts.");Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}});thread.start();try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("main ends.");}}

输出结果为:

main starts.thread0 starts.thread1 starts.thread2 starts.thread3 starts.thread4 starts.main ends.

从输出结果来看,main线程打印了main starts,执行到thread.join()被阻塞了,此时子线程开始打印log,且打印间隔为500ms,当子线程执行完毕后,main线程打印输出main ends。

如果我们将thread.join()改成thread.join(1500),那么输出结果如下:

main starts.thread0 starts.thread1 starts.thread2 starts.main ends.thread3 starts.thread4 starts.

这里采用的是join的一个重载方法,join(long millis),表示等到线程thread执行完毕或者阻塞millis时间后才能允许调用这个函数的线程继续执行下去。从上述输出中我们可以看出main线程并没有等待thread执行完毕,而是等待了1500ms就继续执行了。

其实,这里还可以用这种方法来实现main线程等待thread线程:

//try {//thread.join();//} catch (InterruptedException e) {//e.printStackTrace();//}while(thread.isAlive()){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}

判断thread是否处于alive状态,如果是那么main线程休眠100ms,如果thread结束了,main再继续执行。

2.CountDownLatch

CountDownLatch中维护了一个计数器,初始化时接受一个整型值作为计数器初始值,其中包括两个函数await和countDown,当在某个函数中调用await时,该线程被阻塞,没调用一次countDown计数器值减一,只有当计数器的值为0的时候刚才被阻塞的线程才能继续向下执行。

public class CountDownLatchTest {public static void main(String[] args) throws InterruptedException {final CountDownLatch startCdt = new CountDownLatch(5);final CountDownLatch endCdt = new CountDownLatch(5);for(int i = 0; i < 5; i++){new Thread(new Runnable(){public void run() {System.out.println(Thread.currentThread().getName() + "starts.");try {startCdt.countDown();startCdt.await();//创建的5个线程都在等startCdt的count=0才继续往下执行} catch (InterruptedException e) {e.printStackTrace();}finally{endCdt.countDown();//每个线程执行完后都将count值减1System.out.println(Thread.currentThread().getName() + " ends.");}}}).start();}endCdt.await();//main线程当endCdt的值为0时才继续执行,也就是等上边创建的5个线程执行完毕后才继续执行System.out.println("all threads end.");}


执行结果如下:

Thread-1starts.Thread-3starts.Thread-4starts.Thread-2starts.Thread-0starts.Thread-0 ends.Thread-1 ends.Thread-3 ends.Thread-4 ends.Thread-2 ends.all threads end.

尽管每个子线程创建后立刻执行,但是当他们在运行到startCdt.await()时都被阻塞了,只有startCdt的计数器的值减为0时才继续向下执行;同理main线程在执行到endCdt.await()时阻塞,只有当其计数器减为0时才继续执行。如果没有endCdt.await(),那么执行结果如下:

Thread-1starts.Thread-4starts.Thread-0starts.all threads end.Thread-2starts.Thread-3starts.Thread-3 ends.Thread-1 ends.Thread-4 ends.Thread-0 ends.Thread-2 ends.









原创粉丝点击