文章预览
FutureTask类
重点是那个股票交易处理程序的例子,认真看三遍。本文花了三个小时。
GitHub代码欢迎star。
小白认为学习语言最好的方式就是模仿、思考别人为什么这么写。
FutureTask类同时实现类Runnable接口和Future接口。因此,FutureTask类技能拥有Runnable接口提供的异步计算能力,也能拥有Future接口提供的返回值给调用方的Future对象取消任务的能力。FutureTask类可以用于封装Callable和Runnable接口。
FutureTask<Integer> future = new FutureTaks<Integer>(Callable);
future.run()
run方法会调用任务,并将任务的计算结果赋值给Future对象。
也可以将FutureTask实例交给Executor对象用于执行。
executor.submit(future);
由于FutureTask类也实现了Future接口,因此FutureTak接口实例可以用来取消任务,检查任务等。
创建可取消的任务。
取消任务可以使用执行器返回的Future对象,而创建和执行任务可以使用前面讨论的FutureTask类。
开发可以处理上百万次请求的模拟器。会发送数千条数据交易请求给模拟器。模拟器包含的线程池用于处理这些请求。
还将编写一个“邪恶”的线程,它会随机选择诺干订单,并且尝试取消他们。如果订单已经执行,取消请求会失败。
如果在订单在被分配给线程执行之前接收到取消请求,那么订单会被取消。如果交易订单正在执行。并且线程可被中断,
那么在订单处理过程中接收的取消请求会结束剩余的处理流程。从而取消订单。
public class StocksOrderProcessor {
static final int MAX_NUMBER_OF_ORDER = 1_000_000;
static private ExecutorService executor = Executors.newFixedThreadPool(1000);
static private List<Future> ordersToProcess = new ArrayList<>();
public static class OrderExecutor implements Callable {
int id = 0;
int count = 0;
public OrderExecutor(int id) {
this.id = id;
}
@Override
public Object call() throws Exception {
try {
while (count < 1000) {
count++;
Thread.sleep(new Random(
System.currentTimeMillis() % 10).nextInt(10));
}
System.out.println("Successfully executed order:" + id);
} catch (Exception ex) {
throw (ex);
}
return id;
}
}
}
主函数
public static void main(String[] args) {
System.out.printf("Submitting %d trades%n", MAX_NUMBER_OF_ORDER);
for (int i = 0; i < MAX_NUMBER_OF_ORDER; i++) {
submitOrder(i);
}
new Thread(new EvilThread(ordersToProcess)).start();
System.out.println("Cancelling a few order at random");
try {
executor.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Checking status before shutdown");
int count = 0;
for (Future f : ordersToProcess) {
if (f.isCancelled()) {
count++;
}
}
System.out.printf("%d trades cancelled%n", count);
executor.shutdownNow();
}
private static void submitOrder(int id) {
Callable<Integer> callable = new OrderExecutor(id);
ordersToProcess.add(executor.submit(callable));
}
邪恶线程
class EvilThread implements Runnable {
private List<Future> ordersToProcess;
public EvilThread(List<Future> future) {
this.ordersToProcess = future;
}
@Override
public void run() {
Random myNextKill = new Random(System.currentTimeMillis() % 100);
for (int i = 0; i < 100; i++) {
int index = myNextKill.nextInt(StocksOrderProcessor.MAX_NUMBER_OF_ORDER);
boolean cancel = ordersToProcess.get(index).cancel(true);
if (cancel) {
System.out.println("Cancel Order Succeded:" + index);
} else {
System.out.println("cancel Order Failed:" + index);
}
try {
Thread.sleep(myNextKill.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
程序运行后部分输出如下:
Submitting 1000000 trades
Successfully executed order:28
Successfully executed order:380
Successfully executed order:288
Successfully executed order:120
Cancelling a few order at random
Successfully executed order:116
Successfully executed order:1004
Successfully executed order:1005
Cancel Order Succeded:698021
cancel Order Failed:98832(重点)
...
Successfully executed order:12268
Successfully executed order:12420
Successfully executed order:13190
Successfully executed order:12199
Checking status before shutdown
99 trades cancelled(重点)
Successfully executed order:14045 //估计Kill线程太多了,遗漏这个了.求解.
从输出可以看到:
- 订单698021被成功取消,这个订单还未执行,
- 订单98832的取消请求失败了,因为这个订单已经执行结束.
- 在发送的100个请请求中,有99个被成功取下.也可能是100%,取决你的电脑配置.
………………………………