1. Future和Callable
package a;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class E {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<String> future = pool.submit(new Callable<String>() {
public String call() throws Exception {
Thread.sleep(1000);
return "hello";
}
});
System.out.println("等待结果,可做其他事");
try {
System.out.println("拿到结果:"+future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
package a;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class F {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService=new ExecutorCompletionService<Integer>(threadPool);
for(int i=0;i<10;i++) {
final int seq=i;
completionService.submit(new Callable<Integer>() {
public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(3000));
System.out.println(Thread.currentThread().getName()+"---"+seq);
return seq;
}
});
}
for(int i=0;i<10;i++) {
try {
System.out.println(completionService.take().get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
2.FutherTask和Callable
/**
* 查询多个系统的数据,合并返回
*/
public Object getUserInfo(String userId) throws ExecutionException, InterruptedException {
// 其他例子, 查数据库的多个表数据,分多次查询
// 原味爱好
// Future < > Callable
// 1 和runnable一样的业务定义. 但是本质上是有区别的: 返回值 异常 call run.
Callable<JSONObject> callable = new Callable<JSONObject>() {
@Override
public JSONObject call() throws Exception {
// 1. 先从调用获取用户基础信息的http接口
long userinfoTime = System.currentTimeMillis();
String value = restTemplate.getForObject("http://www.tony.com/userinfo-api/get?userId=" + userId, String.class);
JSONObject userInfo = JSONObject.parseObject(value);
System.out.println("userinfo-api用户基本信息接口调用时间为" + (System.currentTimeMillis() - userinfoTime));
return userInfo;
}
};
// 通过多线程运行callable
// executorService.submit(callable);
FutureTask<JSONObject> userInfoFutureTask = new FutureTask<>(callable);
new Thread(userInfoFutureTask).start();
FutureTask<JSONObject> intergralInfoTask = new FutureTask(() -> {
// 2. 再调用获取用户积分信息的接口
long integralApiTime = System.currentTimeMillis();
String intergral = restTemplate.getForObject("http://www.tony.com/integral-api/get?userId=" + userId,
String.class);
JSONObject intergralInfo = JSONObject.parseObject(intergral);
System.out.println("integral-api积分接口调用时间为" + (System.currentTimeMillis() - integralApiTime));
return intergralInfo;
});
new Thread(intergralInfoTask).start();
// 3. 合并为一个json对象
JSONObject result = new JSONObject();
result.putAll(userInfoFutureTask.get()); // 会等待任务执行结束
result.putAll(intergralInfoTask.get());
return result;
}
手写FutherTask
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;
// 我们想一想,这个功能怎么实现
// (jdk本质,就是利用一些底层API,为开发人员提供便利)
public class NeteaseFutureTask<T> implements Runnable, Future { // 获取 线程异步执行结果 的方式
Callable<T> callable; // 业务逻辑在callable里面
T result = null;
volatile String state = "NEW"; // task执行状态
LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();// 定义一个存储等待者的集合
public NeteaseFutureTask(Callable<T> callable) {
this.callable = callable;
}
@Override
public void run() {
try {
result = callable.call();
} catch (Exception e) {
e.printStackTrace();
// result = exception
} finally {
state = "END";
}
// 唤醒等待者
Thread waiter = waiters.poll();
while (waiter != null) {
LockSupport.unpark(waiter);
waiter = waiters.poll(); // 继续取出队列中的等待者
}
}
// 返回结果,
@Override
public T get() {
if ("END".equals(state)) {
return result;
}
waiters.offer(Thread.currentThread()); // 加入到等待队列,线程不继续往下执行
while (!"END".equals(state)) {
LockSupport.park(); // 线程通信的知识点
}
// 如果没有结束,那么调用get方法的线程,就应该进入等待
return result;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return false;
}
@Override
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
}