闭锁:一种同步工具类,可以用来确保某些活动指导其他活动都完成后才执行。
CountDownLatch:一种闭锁的实现,可以使一个或多个线程等待一组事件发生。
public void CountDownLatch(int count) {...}
CountDownLatch的构造器中的count即线程数(正数),相当于一个递减计数器的作用,count只能初始化时设置一次,之后便不能更改。每个线程完成之后,便立即调用 CountDownLatch.countDown()方法来通知CountDownLatch对象,count减一。count的值等于0,主线程就能通过await()方法,恢复执行自己的任务。await()方法会一直阻塞,直到count为0或等待中的线程中断或等待超时。
FutureTask:一种闭锁的实现,实现了Future接口。可以用来执行一个高开销的计算,并且计算结果将在稍后使用。通过提前启动计算,减少等待结果的时间。Future.get的行为取决于任务的状态。如果任务已经完成,那么get会立即返回结果,否则get将阻塞直到任务进入完成状态,然后返回结果或者抛出异常。
已下内容原文请参考:http://www.cnblogs.com/dolphin0520/p/3949310.html
Callable、Runnable、Future和FutureTask的关系:
java.lang.Runnable是一个接口,在它里面只声明了一个run()方法,且执行完任务之后无法返回任何结果:
public interface Runnable {
public abstract void run();
}
Callable位于java.util.concurrent包下,也是一个接口,在它里面也只声明了一个call()方法,返回的类型就是传递进来的V类型:
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Callable一般配合ExecutorService来使用。
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。Future类位于java.util.concurrent包下,它是一个接口:
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
在Future接口中声明了5个方法,下面依次解释每个方法的作用:
cancel方法:用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
isCancelled方法:表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
isDone方法:表示任务是否已经完成,若任务完成,则返回true;
get()方法:用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
get(long timeout, TimeUnit unit):用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
Future通过这5个方法提供了三种功能:
1)判断任务是否完成;
2)能够中断任务;
3)能够获取任务执行结果。
FutureTask:因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了FutureTask。
FutureTask类实现了RunnableFuture接口,RunnableFuture继承了Runnable接口和Future接口,。所以FutureTask既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
FutureTask提供了2个构造器:
public FutureTask(Callable<V> callable) {
}
public FutureTask(Runnable runnable, V result) {
}
CountDownLatch和FutureTask的区别:CountDownLatch主要是提供一个计数器功能,当所有线程执行完后,在将所有线程一起放行。起到阻塞线程的功能。FutureTask主要对线程的结果进行取消、查询是否完成、获取结果。也可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。即get方法也可以起到阻塞线程的功能。
FutureTask使用Demo:
public class test {
public static void main(String[] args) throws Exception{
test();
}
public static void test() throws Exception{
FutureTask<Student> futureTask = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
return demo1();
}
});
FutureTask<Student> futureTask1 = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
return demo2();
}
});
for (int i=1; i<3 ;i++) {
if(i==1) {
new Thread(futureTask).start();
}else{
new Thread(futureTask1).start();
}
}
Student stu1 = futureTask.get();
System.out.println(stu1);
System.out.println("线程1执行结束");
Student stu2 = futureTask1.get();
System.out.println(stu2);
System.out.println("线程2执行结束");
System.out.println("主线程执行结束====");
}
private static Student demo1() throws Exception{
System.out.println("线程1执行======");
return new Student();
}
private static Student demo2() throws Exception{
System.out.println("线程2开始执行======");
Thread.sleep(5000);
System.out.println("线程2执行结束======");
return new Student();
}
}
class Student{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}