并发编程中的CyclicBarrier之shutdown()与shutdownNow()的区别!

本文介绍Java中CyclicBarrier的使用方法,并通过一个赛马游戏案例演示如何利用shutdownNow()方法来提前终止线程池中的任务。对比shutdown()与shutdownNow()的区别。

CyclicBarrier是java.util.concurrent中的一个类,主要的作用就是用于检测所有的线程是否到达栅栏处,如果没有全部到达,将等待所有线程到达栅栏处,然后处理到达后的逻辑,然后进行下一轮!

shutdown() 作为函数,当然是立即执行,也即是不再接受新任务了;但是它即不会强行终止正在执行的任务,也不会取消已经提交的任务。也就是说之前提交的5个任务,仍然会执行完毕,且跟主线程生命周期无关,也就是即便你直接在后面写上: if (1==1) return; 来立即结束主函数,你也会发现线程池的7个任务会顺利执行完毕。

shutdownNow(),这个函数比shutdown()更狠,两点:
1)、对于尚未执行的任务,全部取消掉;

2)、对于正在执行的任务,发出interrupt()。


举个案例:

一个赛马游戏,如果用shutdown,他不会立即终止正在执行的任务,如果用shutdown就会直接终止掉

package cn.yinganc.cyclicbarrier;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Horse implements Runnable {

	private static int counter = 0;
	private int id = counter++;
	private CyclicBarrier cyclicBarrier;
	private int strides = 0;
	private static Random random = new Random(47);

	public Horse(CyclicBarrier c) {
		cyclicBarrier = c;
	}

	public synchronized int getStrides() {
		return strides;
	}

	@Override
	public void run() {
		try {
			while (!Thread.interrupted()) {
				synchronized (this) {
					strides += random.nextInt(3);
				}
				System.out.println("Horse "+id+"就位");
				cyclicBarrier.await();
			}
		} catch (InterruptedException | BrokenBarrierException e) {
			e.printStackTrace();
		}
	}

	@Override
	public String toString() {
		return "Horse " + id + " ";
	}

	public String tracks() {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < getStrides(); i++) {
			sb.append("*");
		}
		sb.append(id);
		return sb.toString();
	}

}

package cn.yinganc.cyclicbarrier;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class HorseRace {
	static final int FINISH_LINE = 7;
	private List<Horse> list = new ArrayList<Horse>();
	private ExecutorService exec = Executors.newCachedThreadPool();
	private CyclicBarrier cyclicBarrier;
	static volatile boolean isEnd=false;
	public HorseRace(int nHorse, final int pasue) {
		cyclicBarrier = new CyclicBarrier(nHorse, new Runnable() {

			@Override
			public void run() {
				StringBuilder s = new StringBuilder();
				for (int i = 0; i < FINISH_LINE; i++) {
					s.append("=");
				}
				System.out.println(s);
				for (Horse horse : list) {
					System.out.println(horse.tracks());
				}
				for (Horse horse2 : list) {
					if (horse2.getStrides() >= FINISH_LINE  ) {
						System.out.println(horse2 + "won!");
						exec.shutdownNow();
						return ;
					}

				}
				try {
					TimeUnit.MILLISECONDS.sleep(pasue);
				} catch (InterruptedException e) {
					System.out.println("sleep");
				}
			}
		});
		for (int i = 0; i < nHorse; i++) {
			Horse horse = new Horse(cyclicBarrier);
			list.add(horse);
			exec.execute(horse);
		}
	}

	public static void main(String[] args) {
		int nhorse = 7;
		int pasue = 200;
		new HorseRace(nhorse, pasue);
	}
}
输出结果如下:

Horse 0就位
Horse 4就位
Horse 1就位
Horse 2就位
Horse 3就位
Horse 5就位
Horse 6就位
=======
**0
*1
*2
**3
**4
**5
*6
Horse 6就位
Horse 0就位
Horse 4就位
Horse 1就位
Horse 2就位
Horse 3就位
Horse 5就位
=======
**0
*1
*2
**3
***4
***5
***6
Horse 5就位
Horse 6就位
Horse 2就位
Horse 4就位
Horse 1就位
Horse 0就位
Horse 3就位
=======
***0
***1
**2
***3
****4
*****5
****6
Horse 3就位
Horse 5就位
Horse 6就位
Horse 2就位
Horse 4就位
Horse 1就位
Horse 0就位
=======
****0
*****1
****2
***3
****4
******5
****6
Horse 0就位
Horse 2就位
Horse 6就位
Horse 1就位
Horse 5就位
Horse 4就位
Horse 3就位
=======
*****0
******1
*****2
*****3
****4
******5
*****6
Horse 3就位
Horse 6就位
Horse 2就位
Horse 0就位
Horse 1就位
Horse 5就位
Horse 4就位
=======
******0
******1
******2
*****3
******4
******5
*****6
Horse 6就位
Horse 2就位
Horse 4就位
Horse 3就位
Horse 0就位
Horse 1就位
Horse 5就位
=======
*******0
********1
*******2
******3
******4
*******5
*****6
Horse 0 won!

感兴趣的,你可以用shutdown()试试!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值