一个FutureTask示例
第一版
package com.shp.thread;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import org.junit.jupiter.api.Test;
/**
* @author tangcheng
*/
public class FutureTaskTests {
private final Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
long sleep = Double.valueOf(Math.random() * 9 + 1).longValue() * 1000;
System.out.println(String.format("thread %s sleep %s"
, Thread.currentThread().getName(), sleep));
Thread.sleep(sleep);
return Long.valueOf(sleep).intValue();
}
};
@Test
public void allCal() {
ExecutorService executor = Executors.newFixedThreadPool(11);
List<FutureTask<Integer>> tasks = new ArrayList<>();
for (int i = 0; i < 10; i++) {
FutureTask<Integer> task = new FutureTask<>(callable);
tasks.add(task);
executor.execute(task);
}
int result = 0;
long start = System.currentTimeMillis();
for (; ; ) {
if (tasks.isEmpty())
break;
Iterator<FutureTask<Integer>> iterator = tasks.iterator();
while (iterator.hasNext()) {
FutureTask<Integer> task = iterator.next();
// Callable中任务执行时间过长时,会造成CPU空转,占用率高
if (!task.isDone()) {
continue;
}
try {
result = result + task.get();
System.out.println("add =>" + task.get());
iterator.remove();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
break;
} catch (ExecutionException e) {
e.printStackTrace();
throw e;
}
}
if (Thread.interrupted())
break;
}
executor.shutdown();
System.out.println(String.format("result=%s, spend=%s"
, result, (System.currentTimeMillis() - start) / 1000));
}
}
// created at 2022/6/14 14:04
顺序执行需要47秒,多线程执行需要8秒。
第二版
利用CountDownLatch,避免CPU空转
package com.shp.thread;
import java.util.ArrayList;
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.FutureTask;
import org.junit.jupiter.api.Test;
/**
* @author tangcheng
*/
public class FutureTask2Tests {
private static class Worker<F> implements Runnable {
private final CountDownLatch countDownLatch;
private final FutureTask<F> futureTask;
private Worker(CountDownLatch countDownLatch
, FutureTask<F> futureTask) {
this.countDownLatch = countDownLatch;
this.futureTask = futureTask;
}
@Override
public void run() {
futureTask.run();
F res = null;
try {
res = futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println(String.format("thread = %s, result=%s"
, Thread.currentThread().getName(), res));
countDownLatch.countDown();
}
}
private final Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
long sleep = Double.valueOf(Math.random() * 9 + 1)
.longValue() * 1000;
System.out.println(String.format("thread %s sleep %s"
, Thread.currentThread().getName(), sleep));
Thread.sleep(sleep);
return Long.valueOf(sleep).intValue();
}
};
@Test
public void allCal() {
ExecutorService executor = Executors.newFixedThreadPool(11);
List<FutureTask<Integer>> tasks = new ArrayList<>();
final int count = 10;
CountDownLatch countDownLatch = new CountDownLatch(count);
for (int i = 0; i < count; i++) {
FutureTask<Integer> task = new FutureTask<>(callable);
tasks.add(task);
executor.execute(new Worker<>(countDownLatch, task));
}
long start = System.currentTimeMillis();
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
int result = 0;
for (FutureTask<Integer> task : tasks) {
try {
result = result + task.get();
} catch (InterruptedException | ExecutionException e) {
// ignore
}
}
executor.shutdown();
System.out.println(String.format("result=%s, spend=%s"
, result, (System.currentTimeMillis() - start) / 1000));
}
}
// created at 2022/6/14 14:04