java并发包concurrent多线程示例

本文介绍了Java并发包中Callable和Future接口的使用,通过call()方法实现带返回值的任务。同时讲解了CountDownLatch如何作为计时器,通过await()和countDown()控制线程同步。还提到了ExecutorService和Executors作为线程池的使用。文中通过一个5个选手赛跑的场景,展示了如何应用这些并发工具,主线程作为裁判,等待所有选手完成任务并收集结果。

Callable/Future

CountDownLatch

ExecutorService/Executors

主要是以上几个并发包类的用法、



简单描述下:


Callable/Future   : Callable<T>这个接口类似于Runnble接口,要重写里面的call()方法(类似于run方法)具体区别是,call()可以返回值T,run()不能返回、返回的值通过Future.get()获得。


CountDownLatch :这个是一个计时器,主要方法是 await() 和countDown()  ,  await() 是一个阻塞式的,等countDown()  调用完再执行下面的代码。countDown()要调N次,在构造CountDownLatch 的时候,要指定N次。  可以实现一个  总分总  的线程模型。


ExecutorService/Executors:  这个是线程池的内容,大家记住就行,到时候用的时候再查,线程池总类有些多,要根据具体场景才能选择合适自己的池。


下面实例程序,有些长,大家慢慢看,写程序的要静的下心。

/////// 描述下场景。

就是5个选手赛跑,每个选手有个能量值,在初始化选手的时候可以给定,值越高,跑得越快。(最高不高过5,不小过0).

主线程可以看作是裁判,他在起跑线上等待5个选手初始化。每个选手初始化完后,在起跑线上$begin.await(); // //等begin.countDown();这条开始命令

begin.countDown();后,每个选手都开始跑了,然后主线程在等着end.await(); // /主线程在这里等他们跑(阻塞式),跑完之后收集他们的结果,然后评出排名.。

当每个选手跑完后,end.countDown()一下,意思是我跑完了。直到5个人都end.countDown()一下后,主线程就执行end.await()方法下面的代码了。就是开始

收集他们的成绩,然后统计,然后输出。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 
 * @author caogu.wyp
 *
 */
public class Run {

	public static void main(String[] args) {
		CountDownLatch begin = new CountDownLatch(1); // /这个是开始的信号(begin初始化为1,当begin.countDown()为0时,begin.await()可以开始执行)
		CountDownLatch end = new CountDownLatch(5); // /这个是结束的信号(end初始化为5,当调用5次end.countDown()减为0时,end.await()可以开始执行)
		List<Future<Runner>> fs = new ArrayList<Future<Runner>>(); // /这个用来保存每个选手跑的时间
		ExecutorService es = Executors.newFixedThreadPool(10);

		Runner r1 = new Runner(1 + "号选手:", 5);
		Runner r2 = new Runner(2 + "号选手:", 1);
		Runner r3 = new Runner(3 + "号选手:", 4);
		Runner r4 = new Runner(4 + "号选手:", 3);
		Runner r5 = new Runner(5 + "号选手:", 3);
		
		fs.add(es.submit(new T(r1, begin, end)));
		fs.add(es.submit(new T(r2, begin, end)));
		fs.add(es.submit(new T(r3, begin, end)));
		fs.add(es.submit(new T(r4, begin, end)));
		fs.add(es.submit(new T(r5, begin, end)));

		
		for(int i = 3 ;i>0 ;i--)    ///倒计时
		{
			try {
				Thread.sleep(1000);
				System.out.println(i);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("开始");
		begin.countDown(); // /主线程这里说开始,子线那里才可以开始跑(这里阻塞着选手)
		try {
			end.await(); // /主线程在这里等他们跑(阻塞式),跑完之后收集他们的结果,然后评出排名.
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("大家都跑完了 开始计算结果,大家稍等下");

		List<Runner> sort = new ArrayList<Runner>();
		for (Future<Runner> f : fs) {//////////////////////这里在等所有的子线程完成
			try {
				sort.add(f.get());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		Collections.sort(sort);
		for (int i = 0; i < sort.size(); i++) {
			System.out.println("第" + (i + 1) + "名:" + sort.get(i).$name + ":"
					+ "成绩" + sort.get(i).$time + "秒." + " 能量:"
					+ sort.get(i).$power);
		}
		// ////跑完了。
		es.shutdown();

	}

	static class T implements Callable<Runner> {
		private Runner $runner;
		private CountDownLatch $begin;
		private CountDownLatch $end;

		public T(Runner _runner, CountDownLatch _begin, CountDownLatch _end) {
			$begin = _begin;
			$end = _end;
			this.$runner = _runner;
		}

		@Override
		public Runner call() throws Exception {
			// TODO Auto-generated method stub

			$begin.await(); // //等begin.countDown();这条开始命令
			System.out.println("大家好,我是" + $runner.$name + "开跑了.");
			$runner.run(); // //跑啊跑啊跑啊跑啊
			$end.countDown(); // 到了,你妹! 快掐表!!!我的成绩是s!
			return $runner;
		}
	}

	static class Runner implements Comparable<Runner> {
		private String $name;
		private int $power;   ////这个是选手的能量值,初始化选手的时候给定的,能量值越多,跑得越快
		private long $time;   /////跑的时间

		public long get$time() {
			return $time;
		}

		public void set$time(long $time) {
			this.$time = $time;
		}

		public String get$name() {
			return $name;
		}

		public void set$name(String $name) {
			this.$name = $name;
		}

		public int get$power() {
			return $power;
		}

		public void set$power(int $power) {
			this.$power = $power;
		}

		public Runner(String _name, int _power) {
			this.$name = _name;
			this.$power = _power;
		}

		public void run() {
			// //
			long st = System.currentTimeMillis();
			if ($power > 5 || $power < 0) //
				try {
					throw new Exception();
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			try {
				Thread.sleep(5000 - 1000 * $power);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} // 跑步的能力,能力越大,睡的时间越段
			$time = System.currentTimeMillis() - st;
		}

		@Override
		public int compareTo(Runner o) {
			// TODO Auto-generated method stub
			if (this.$time < o.$time)
				return -1;
			if (this.$time > o.$time)
				return 1;
			return 0;
		}
	}
}


结果:


3
2
1
开始
大家好,我是2号选手:开跑了.
大家好,我是5号选手:开跑了.
大家好,我是3号选手:开跑了.
大家好,我是1号选手:开跑了.
大家好,我是4号选手:开跑了.
大家都跑完了 开始计算结果,大家稍等下
第1名:1号选手::成绩0秒. 能量:5
第2名:3号选手::成绩1000秒. 能量:4
第3名:4号选手::成绩2000秒. 能量:3
第4名:5号选手::成绩2000秒. 能量:3
第5名:2号选手::成绩4000秒. 能量:1


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值