package study.java.jdks.version1_5.concurrent;
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 hadoop2
* 问题,.await()方法什么时候不阻塞
*/
public class ThreadTest {
public static String test = "fucheng";
public static void main(String[] args) {
// 这个是开始的信号(begin初始化为1,当begin.countDown()为0时,begin.await()可以开始执行)
CountDownLatch begin = new CountDownLatch(1);
// 这个是结束的信号(end初始化为5,当调用5次end.countDown()减为0时,end.await()可以开始执行)
CountDownLatch end = new CountDownLatch(5);
// 这个用来保存每个选手跑的时间
List<Future<Runner>> fs = new ArrayList<Future<Runner>>();
ExecutorService es = Executors.newFixedThreadPool(10);
//new Sych
// new CachedThreadPool();
//SynchronousQueue
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) {
e.printStackTrace();
}
}
System.out.println("开始");
// 主线程这里说开始,子线那里才可以开始跑(这里阻塞着选手)
begin.countDown();
// try {
// Thread.sleep(1);
// } catch (InterruptedException e1) {
// e1.printStackTrace();
// }
test = "fucheng changed";
try {
// 主线程在这里等他们跑(阻塞式),跑完之后收集他们的结果,然后评出排名.
end.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("大家都跑完了 开始计算结果,大家稍等下");
List<Runner> sort = new ArrayList<Runner>();
for (Future<Runner> f : fs) {//////////////////////这里在等所有的子线程完成
try {
// f.get()方法阻塞当前线程
sort.add(f.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
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 {
$begin.await(); // //等begin.countDown();这条开始命令
System.out.println(ThreadTest.test);
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;
}
}
}
/**
说明:
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()方法下面的代码了。就是开始收集他们的成绩,然后统计,然后输出。
*/