java.util.concurrent包和Future模式

java.util.concurrent包

java.util.concurrent包提供了用于支持Future模式的类和接口。

java.util.concurrent.Callable接口将“返回值的某种处理的调用”抽象化了。Callable接口声明了call方法。call方法与Runnable接口的run方法相似,不同的是call方法有返回值。

java.util.concurrent.Future接口相当于Future角色。Future接口声明了用于获取值的get方法,但并没有声明设置值的方法。设置值的方法需要在实现Future接口的类中声明。除了get方法外,Future接口还声明了用于中断运行的cancel方法。

java.util.concurrent.FutureTask类是实现了Future接口的标准类。FutureTask类声明了用于获取值的get方法、用于中断运行的cancel方法、用于设置值的set方法,以及用于设置异常的setException方法。此外,由于FutureTask类还实现了Runnable接口,所以它还声明了run方法。

k3C82t.png

在创建FutureTask类的实例时,Callable对象会被传递给构造函数的参数。之后,如果线程调用FutureTask的run方法,那么在构造函数中接收到的参数——Callable对象的call方法就会被执行。换言之,调用FutureTask的run方法的线程也会调用call方法。
调用call方法的线程会同步地获取call方法的返回值,然后通过FutureTask的set方法来设置该返回值。如果call方法中发生了异常,则调用call方法的线程就会调用FutureTask的setException方法设置异常。
再然后,只要根据需要,调用FutureTask的get方法去获取值,就可以获取call方法的返回值。其中,get方法无论由哪个线程调用都可以。

使用java.util.concurrent包

Host.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.concurrent.Callable;

public class Host {
public Data request(final int count, final char c) {
System.out.println(" request(" + count + ", " + c + ") BEGIN");

FutureData future = new FutureData(
new Callable<RealData>() {
@Override
public RealData call() throws Exception {
return new RealData(count, c);
}
}
);

new Thread(future).start();

System.out.println(" request(" + count + ", " + c + ") END");
return future;
}
}

FutureData.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureData extends FutureTask<RealData> implements Data {

public FutureData(Callable<RealData> callable) {
super(callable);
}


@Override
public String getContent() {
String string = null;

try {
string = get().getContent();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

return string;
}
}

时序图

k3PMLT.png