Comparison and use of Cyclicbarrier and Countdownlatch

CountDownLatch

Package name: java.util.concurrent

Purpose: Execute after waiting for other threads to finish executing

Main method:

Constructor

/**
     * Constructs a {@code CountDownLatch} initialized with the given count.
     *
     * @param count the number of times {@link #countDown} must be invoked
     *        before threads can pass through {@link #await}
     * @throws IllegalArgumentException if {@code count} is negative
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

Thread waiting can set a timeout

  public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
  public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

The counter is decremented by 1. Each thread executes the method and calls the method once until the value of count is 0.

public void countDown() {
        sync.releaseShared(1);
    }

use demo

  1. Implement a Runnable yourself, pass in the CountDownLatch parameter
/**
 * 描述:
 * 使用countdownlatch
 *
 * @author Kipeng Huang
 * @create 2018-03-03 下午1:28
 */
public class CountRunnable implements Runnable {
	private CountDownLatch countDownLatch;

	public CountRunnable(CountDownLatch countDownLatch) {
		this.countDownLatch = countDownLatch;
	}

	/**
	 * countDownLatch.countDown();  放在finally中执行
	 */
	@Override
	public void run() {
		try {
			//打印线程名称
			System.out.println(Thread.currentThread().getName());
			System.out.println("开始处理数据...");
			Thread.sleep(3000L);
			System.out.println("数据处理完毕...");

		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			countDownLatch.countDown();
		}

	}
}
  1. test the main method
/**
 * 描述:
 *
 * @author Kipeng Huang
 * @create 2018-03-03 下午1:32
 */
public class TestCountDownLatch {

	public static void main(String[] args) throws InterruptedException {
		CountDownLatch countDownLatch = new CountDownLatch(20);
		//可以定义线程名称规则
		ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
				.setNameFormat("demo-pool-%d").build();
		//使用阿里Java规范自己创建线程池
		ExecutorService threadPool = new ThreadPoolExecutor(4,
				20,
				1000L,
				TimeUnit.MILLISECONDS,
				new ArrayBlockingQueue<Runnable>(1024),
				namedThreadFactory,
				new ThreadPoolExecutor.AbortPolicy());
		for (int i = 0; i < 20; i++) {
			threadPool.execute(new CountRunnable(countDownLatch));
		}
		countDownLatch.await();
		System.out.println("全部数据处理完毕");
		threadPool.shutdown();
	}
}
  1. Results of the
demo-pool-0
开始处理数据...
demo-pool-1
开始处理数据...
demo-pool-2
开始处理数据...
demo-pool-3
开始处理数据...
数据处理完毕...
数据处理完毕...
demo-pool-1
demo-pool-0
开始处理数据...
开始处理数据...
数据处理完毕...
demo-pool-2
开始处理数据...
数据处理完毕...
demo-pool-3
开始处理数据...
数据处理完毕...
数据处理完毕...
demo-pool-0
开始处理数据...
demo-pool-1
开始处理数据...
数据处理完毕...
demo-pool-2
开始处理数据...
数据处理完毕...
demo-pool-3
开始处理数据...
数据处理完毕...
数据处理完毕...
demo-pool-0
开始处理数据...
demo-pool-1
开始处理数据...
数据处理完毕...
demo-pool-2
开始处理数据...
数据处理完毕...
demo-pool-3
开始处理数据...
数据处理完毕...
demo-pool-0
开始处理数据...
数据处理完毕...
demo-pool-1
开始处理数据...
数据处理完毕...
demo-pool-2
开始处理数据...
数据处理完毕...
demo-pool-3
开始处理数据...
数据处理完毕...
数据处理完毕...
数据处理完毕...
数据处理完毕...
全部数据处理完毕

Process finished with exit code 0

It can be seen from the execution results that the main thread has been blocked until the count is 0.

CyclicBarrier

Package name: java.util.concurrent

Purpose: It can be used to make a group of threads wait to a certain state and then execute all at the same time

The main two construction methods

    /**
     * @param parties 表示有多少线程阻塞在这里等待
     * @param barrierAction 满足条件后执行这个任务
    */
    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }

    /**
     * Creates a new {@code CyclicBarrier} that will trip when the
     * given number of parties (threads) are waiting upon it, and
     * does not perform a predefined action when the barrier is tripped.
     *
     * @param parties 表示有多少线程阻塞在这里等待
     * @throws IllegalArgumentException if {@code parties} is less than 1
     */
    public CyclicBarrier(int parties) {
        this(parties, null);
    }

use demo


/**
 * 描述:
 *
 * @author Kipeng Huang
 * @create 2018-03-03 下午2:10
 */
public class CycleBarrierRunnable implements Runnable {
	private CyclicBarrier cyclicBarrier;

	public CycleBarrierRunnable(CyclicBarrier cyclicBarrier) {
		this.cyclicBarrier = cyclicBarrier;
	}


	@Override
	public void run() {
		System.out.println("当前线程名:" + Thread.currentThread().getName());
		try {
			Thread.sleep(2000);
			cyclicBarrier.await();
			System.out.println("线程" + Thread.currentThread().getName() + "执行完毕");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}

	}
}
/**
 * 描述:
 *
 * @author Kipeng Huang
 * @create 2018-03-03 下午2:21
 */
public class BarrierTest {

	public static void main(String[] args) {
		ThreadFactory threadFactory = new ThreadFactoryBuilder()
				.setNameFormat("demo-pool-%d")
				.build();
		ExecutorService threadPool = new ThreadPoolExecutor(20,
				20,
				2000L,
				TimeUnit.MILLISECONDS,
				new ArrayBlockingQueue<Runnable>(1024),
				threadFactory,
				new ThreadPoolExecutor.AbortPolicy());

		CyclicBarrier cyclicBarrier = new CyclicBarrier(20);

		for (int i = 0; i < 20; i++) {
			threadPool.execute(new CycleBarrierRunnable(cyclicBarrier));
		}
		cyclicBarrier.reset();
		System.out.println("主线程程序执行");
		threadPool.shutdown();

	}
}
当前线程名:demo-pool-0
当前线程名:demo-pool-1
当前线程名:demo-pool-2
当前线程名:demo-pool-3
当前线程名:demo-pool-4
当前线程名:demo-pool-5
当前线程名:demo-pool-6
当前线程名:demo-pool-7
当前线程名:demo-pool-8
当前线程名:demo-pool-9
当前线程名:demo-pool-10
当前线程名:demo-pool-11
当前线程名:demo-pool-12
当前线程名:demo-pool-13
当前线程名:demo-pool-14
当前线程名:demo-pool-15
当前线程名:demo-pool-16
当前线程名:demo-pool-17
当前线程名:demo-pool-18
主线程程序执行
当前线程名:demo-pool-19
线程demo-pool-19执行完毕
线程demo-pool-1执行完毕
线程demo-pool-3执行完毕
线程demo-pool-4执行完毕
线程demo-pool-8执行完毕
线程demo-pool-0执行完毕
线程demo-pool-11执行完毕
线程demo-pool-10执行完毕
线程demo-pool-9执行完毕
线程demo-pool-6执行完毕
线程demo-pool-7执行完毕
线程demo-pool-5执行完毕
线程demo-pool-2执行完毕
线程demo-pool-17执行完毕
线程demo-pool-18执行完毕
线程demo-pool-16执行完毕
线程demo-pool-15执行完毕
线程demo-pool-13执行完毕
线程demo-pool-14执行完毕
线程demo-pool-12执行完毕

Process finished with exit code 0

Precautions

If the number of core threads in the thread pool is less than the number of CyclicBarrier, it will always block. unable to execute

ExecutorService threadPool = new ThreadPoolExecutor(3,
				20,
				2000L,
				TimeUnit.MILLISECONDS,
				new ArrayBlockingQueue<Runnable>(1024),
				threadFactory,
				new ThreadPoolExecutor.AbortPolicy());

Results of the

当前线程名:demo-pool-0
当前线程名:demo-pool-1
当前线程名:demo-pool-2
主线程程序执行

Difference between Cyclicbarrier and Countdownlatch

|CountDownLatch|CyclicBarrier| | -- | -- | | Cardinality subtraction method | Cardinality addition method | | Release all waiting threads when the count is 0 | Release all waiting threads when the cardinality reaches the specified value | | Reset, can only be used once | When the cardinality reaches the specified value, the count is set to 0 and restarts | | Call the countDown method to subtract one, the await method blocks | Call the await method | | Not reusable | Reusable |

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325261438&siteId=291194637
Recommended