多个线程的同步(所有任务都完成之后再向下执行)--转

主要是使用CountDownLatch

CountDownlatch,是一种Sychronizer,它可以延迟线程的进度直到线程的进度到线程到达终止状态。

它本身而言是Java并发包中非常有用的一个类,它可以让某些任务完成以后再继续运行下面的内容,每个任务本身执行完毕后让计数器减一,直到计数器清零后,以下的内容才可以继续运行,否则将阻塞等待。

想了一下,这个场景非常适合用于项目中这样的场景: 我们有个项目,它需要三个第三方的API,并把结果拿到,在一个线程中顺序去拿结果没有问题,但是这里这三个任务是非常耗时的操作,如果顺序获取性能非常差,因此可以考虑用三个线程,当三个线程拿到结果后才继续主线程的工作,等三个线程运行结束后,由主线程去取子线程运行的结果。 这里有个很重要的前提:我们的系统运行在4个cpu的server上,这样多线程才能体现性能,JVM会分配这些线程尽量运行在不同的cpu上。

CountDownLatch有以下基本方法:

1)await(),阻塞等待,直到计数器清零

2)await(int timeout, TimeUnit unit),使线程阻塞,除非被中断或者超过等待的最大时间

如果达到计数器清零,则await返回true,如果等待超过了最大的等待时间,则返回false

3)countDown(),计数器减一,当计数器清零时,await的线程被唤醒,线程继续执行

4)getCount (),获取当前计数器的大小

package countdownlatch;

import java.util.concurrent.CountDownLatch;

/**
 *
 *<p>Test</p>
 *<p>Description:</P>
 *<p>Company:</p>
 *<p>Department:CAS</p>
 *@Author: Tommy Zhou
 *@Since: 1.0
 *@Version:Date:2011-4-26
 *
 **/

public class CountDownLatchSample {

    public static void main(String[] args) {
        String[] strs = getResult();
        for (int i = 0; i < strs.length; i++) {
            System.out.println(strs[i]);
        }

    }

    public static String[] getResult(){
        String[] strs = new String[3];
        CountDownLatch countDownLatch = new CountDownLatch(3);
        Work1 work1 = new Work1(countDownLatch,strs[0]);
        Work2 work2 = new Work2(countDownLatch,strs[1]);
        Work3 work3 = new Work3(countDownLatch,strs[2]);
        work1.start();
        work2.start();
        work3.start();
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        strs[0] = work1.str1;
        strs[1] = work2.str2;
        strs[2] = work3.str3;
        return strs;
    }
}

class Work1 extends Thread{
    public String str1;
    public CountDownLatch latch1;
    public Work1(CountDownLatch latch1,String str1){
        this.latch1 = latch1;
        this.str1 = str1;
    }

    public void run(){
        str1="work1";
        latch1.countDown();
    }
}

class Work2 extends Thread{
    public String str2;
    public CountDownLatch latch2;
    public Work2(CountDownLatch latch2,String str2){
        this.latch2 = latch2;
        this.str2 = str2;
    }

    public void run(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        str2="work2";
        latch2.countDown();
    }
}

class Work3 extends Thread{
    public String str3;
    public CountDownLatch latch3;
    public Work3(CountDownLatch latch3,String str3){
        this.latch3 = latch3;
        this.str3 = str3;
    }

    public void run(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        str3="work3";
        latch3.countDown();
    }
}
时间: 2024-11-05 18:44:29

多个线程的同步(所有任务都完成之后再向下执行)--转的相关文章

IOS 等待条件满足再向下执行但不主卡线程NSRunLoop

当我们需要等一个异步的结果才能向下执行代码,写回调又很麻烦,功能相对简单的时候,就可以插入以下红色部分的代码. - (IBAction)start:(id)sender{pageStillLoading = YES;[NSThread detachNewThreadSelector:@selector(loadPageInBackground:)toTarget:self withObject:nil];[progress setHidden:NO];while (pageStillLoadin

Linux下线程的同步与互斥

一.线程的互斥 多个线程同时访问共享数据时可能会冲突,跟之前信号量的可重如性是同样的问题.如两个线程都要把某个全局变量增加1,这个操作在某平台需要三条指令完成: 1. 从内存读变量值到寄存器 2. 寄存器的值加1 3. 将寄存器的值写回内存 如下程序就会产生问题: 我们创建两个线程,每把g_count增加5000次,正常情况下最后g_count应该等于10000,但事实上每次运行该程序的结果都不一样. 对于多线程的程序,访问冲突的问题是很普遍的,解决的办法是引入互斥锁(Mutex,Mutual

linux线程间同步方式汇总

抽空做了下linux所有线程间同步方式的汇总(原生的),包含以下几个: 1, mutex 2, condition variable 3, reader-writer lock 4, spin lock 5, barrier mutex是最常用的线程间同步方式,主要目的是保护共享的资源可以被原子地访问. 个人感觉condition variable是除了mutex之外的第二常用的线程间同步方式,可以用来以同步的方式使用一个线程来通知另一个线程某个事件已经发生.可以理解为线程间的信号. reade

[Java Performance] 线程及同步的性能 - 线程池/ThreadPoolExecutors/ForkJoinPool

线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自客户端的请求.Java中对于线程池的支持,来自ThreadPoolExecutor.一些应用服务器也确实是使用的ThreadPoolExecutor来实现线程池. 对于线程池的性能调优,最重要的参数就是线程池的大小. 对于任何线程池而言,它们的工作方式几乎都是相同的: 任务被投放到一个队列中(队列的

线程+任务+同步

线程: 对于所有需要等待的操作,例如移动文件,数据库和网络访问都需要一定的时间,此时就可以启动一个新的线程,同时完成其他任务.一个进程的多个线程可以同时运行在不同的CPU上或多核CPU的不同内核上. 线程是程序中独立的指令流.在VS编辑器中输入代码的时候,系统会分析代码,用下划线标注遗漏的分号和其他语法错误,这就是用一个后台线程完成.Word文档需要一个线程等待用户输入,另一个线程进行后台搜索,第三个线程将写入的数据存储在临时文件中.运行在服务器上的应用程序中等待客户请求的线程成为侦听器线程.

线程间同步之信号量实现环形buf

一.概述: 信号量是一个非负整数的计数器,它通过计数器来实现多线程对临界资源的顺序访问,从而实现线程间的同步.它与进程间通信的信号量不同,进程间通信的信号量是一个信号量集,而线程间同步的信号量是一个信号.还有一点,就是对信号量的操作是原子的. 信号量与互斥锁的区别: (1).互斥锁的值只能是0或1,而信号量的值为非负整数. (2).互斥锁用与实现线程间的互斥,而信号量用于实现线程间的同步. (3).互斥锁的加锁和解锁必须由同一个线程分别对应使用,而信号量可以由一个线程得到,另一个线程释放. 下面

线程的同步与互斥,死锁

线程的同步与互斥 多个线程同时访问共享数据时可能会发生冲突,比如两个线程同时把一个全局变量加1,结果可能不是我们所期待的: 我们看这段代码的执行结果: #include <stdio.h> #include <stdlib.h> #include <pthread.h> static int g_count=0; void *thread(void *arg) { int index=0; int tmp=0; while(index++<5000) { tmp=

线程和同步

线程和同步 1 概述 对于所有需要等待 的操作,例 如 ,因 为文件 . 数据库或网络访 问都需要一定 的时间,此 时就可以启 动一个新线程,同时完成其他任务,即使是处理密集型的任务,线程也是有帮助的. 2 Parallel类 2.1 用Parallel.For()方法循环 Parallel.For()方法类似于C#的For循环,多次执行一个任务,它可以并行运行迭代.迭代的顺序没有定义. 1 ParallelLoopResult result = Parallel.For(0, 10, i =>

Java线程:线程的同步与锁

一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. public class Foo {     private int x = 100; public int getX() {         return x;     } public int fix(int y) {         x = x - y;         return x;     } }