java多线程之CountDownLatch(1)(模拟高并发和开会问题)

一、简介

CountDownLatch 是 java.util.concurrent 包下的一个同步辅助类,它能使一个或多个线程在其他的线程的一系列操作完成之前一直等待,初始化值为计数器大小(即线程数量)。

二、使用场景

  1. 同时启动多个线程;
  2. 多个线程操作完成之前一直等待。

注:此处“同时”只能是“大约同时”,涉及到每个线程是否可以分配到一个自由的处理器,系统是否繁忙,线程释放CPU的速度,线程的优先级等等诸多因素。

三、主要方法

await() 方法是线程阻塞,直到计数器为0,才会启动; 
countDown() 方法使计数器减1。

四、实例

1、高并发实例:此处为模拟100个线程同时对一条数据进行加1操作

package com.wlm.test.concurrent;

import java.util.concurrent.CountDownLatch;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wlm.test.award.AwardDao;

/**
 * @author wengliemiao
 */
@Service
public class ConcurrentTest {
    @Autowired
    private AwardDao awardDao;

    /**
     * 线程数量
     */
    public static final int THREAD_NUM = 100;

    /**
     * 开始时间
     */
    private static long startTime = 0L;

    @PostConstruct
    public void init() {
        try {
            startTime = System.currentTimeMillis();
            System.out.println("CountDownLatch started at: " + startTime);

            // 初始化计数器为1
            CountDownLatch countDownLatch = new CountDownLatch(1);

            for (int i = 0; i < THREAD_NUM; i ++) {
                new Thread(new Run(countDownLatch)).start();
            }

            // 启动多个线程
            countDownLatch.countDown();

        } catch (Exception e) {
            System.out.println("Exception: " + e);
        }
    }

    /**
     * 线程类
     */
    private class Run implements Runnable {
        private final CountDownLatch startLatch;

        public Run(CountDownLatch startLatch) {
            this.startLatch = startLatch;
        }

        @Override
        public void run() {
            try {
                // 线程等待
                startLatch.await();

                // 执行操作
                awardDao.update(3);

                long endTime = System.currentTimeMillis();
                System.out.println(Thread.currentThread().getName() + " ended at: " + endTime + ", cost: " + (endTime - startTime) + " ms.");
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

运行前: 
这里写图片描述

运行后: 
这里写图片描述

这里写图片描述

2、等待多个线程处理实例:

package com.wlm.test.concurrent;

import java.util.concurrent.CountDownLatch;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Service;

/**
 * @author wengliemiao
 */
@Service
public class WaitThreadTest {

    @PostConstruct
    public void init() {
        try {
            System.out.println("******************** WaitThreadTest started at:" + System.currentTimeMillis() + " ********************");
            CountDownLatch stopLatch = new CountDownLatch(3);

            for (int i = 0; i < 3; i ++) {
                new Thread(new Run(stopLatch)).start();
            }

            // 等待所有线程操作完成
            stopLatch.await();

            System.out.println("******************** WaitThreadTest ended at:" + System.currentTimeMillis() + " ********************");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class Run implements Runnable {

        private CountDownLatch stopLatch;

        public Run(CountDownLatch countDownLatch) {
            this.stopLatch = countDownLatch;
        }

        @Override
        public void run() {
            // 线程操作
            System.out.println(Thread.currentThread().getName() + " Handler...");

            // 线程结束操作
            stopLatch.countDown();
        }
    }

}

运行结果:

这里写图片描述

四、InterruptedException

如果当前线程设置了 interrupted 状态,或者在调用 await() 方法之后等待的过程中,被其他线程打断(如调用 interrupt() 方法),会抛出 InterruptedException 异常,因此最好捕捉相应的异常。

你可能感兴趣的:(Java并发和多线程操作)