传统JDK中的Future通过异步的方式计算返回结果:在多线程运算中可能或者可能在没有结束返回结果,Future是运行中的多线程的一个引用句柄,确保在服务执行返回一个Result。
ListenableFuture可以允许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用, 或者在运算(多线程执行)完成后立即执行。这样简单的改进,使得可以明显的支持更多的操作,这样的功能在JDK concurrent中的Future是不支持的。
ListenableFuture 中的基础方法是addListener(Runnable, Executor), 该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行。
多数用户喜欢使用 Futures.addCallback(ListenableFuture
对应JDK中的 ExecutorService.submit(Callable) 提交多线程异步运算的方式,Guava 提供了ListeningExecutorService 接口, 该接口返回 ListenableFuture 而相应的 ExecutorService 返回普通的 Future。将 ExecutorService 转为 ListeningExecutorService,可以使用MoreExecutors.listeningDecorator(ExecutorService)进行装饰。
package com.redisson;
import com.google.common.util.concurrent.*;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import javax.annotation.Nullable;
import java.util.concurrent.*;
/**
* @Description TODO
* @Date 2020/6/30 10:29
* @Author zsj
*/
public class RedissonTest {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 10, 60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(200),
new ThreadPoolExecutor.CallerRunsPolicy());
ListeningExecutorService service = MoreExecutors.listeningDecorator(threadPoolExecutor);
ListenableFuture future = service.submit(new Callable() {
@Override
public String call(){
Integer.parseInt("ww");
return "22";
}
});
Futures.addCallback(future, new FutureCallback() {
@Override
public void onSuccess(String o) {
System.out.println(o);
}
@Override
public void onFailure(Throwable throwable) {
throwable.printStackTrace();
}
});
threadPoolExecutor.shutdown();
}
}
3、CountDownLatch 结合ListenableFuture
package com.redisson;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
/**
* @Description TODO
* @Date 2020/7/2 9:23
* @Author zsj
*/
public class Test {
/**
* 线程池
*/
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 10, 60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(200),
new ThreadPoolExecutor.CallerRunsPolicy()
);
public static void main(String[] args) {
List result = Collections.synchronizedList(new ArrayList<>());
List list = Collections.synchronizedList(new ArrayList<>());
//模拟原始数据
for (int i = 0; i < 1211; i++) {
list.add(i + "-");
}
int size = 50;//切分粒度,每size条数据,切分一块,交由一条线程处理
int countNum = 0;//当前处理到的位置
int count = list.size() / size;//切分块数
int threadNum = 0;//使用线程数
if (count * size != list.size()) {
count++;
}
final CountDownLatch countDownLatch = new CountDownLatch(count);
//使用Guava的ListeningExecutorService装饰线程池
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(threadPoolExecutor);
while (countNum < count * size) {
//切割不同的数据块,分段处理
threadNum++;
countNum += size;
MyCallable myCallable = new MyCallable();
myCallable.setList(ImmutableList.copyOf(
list.subList(countNum - size, list.size() > countNum ? countNum : list.size())));
ListenableFuture listenableFuture = executorService.submit(myCallable);
//回调函数
int finalThreadNum = threadNum;
Futures.addCallback(listenableFuture, new FutureCallback>() {
//任务处理成功时执行
@Override
public void onSuccess(List list) {
countDownLatch.countDown();
System.out.println("第"+ finalThreadNum +"次处理完成");
result.addAll(list);
}
//任务处理失败时执行
@Override
public void onFailure(Throwable throwable) {
countDownLatch.countDown();
System.out.println("处理失败:" + throwable);
}
});
}
try {
//设置时间,超时了直接向下执行,不再阻塞
// countDownLatch.await(3, TimeUnit.SECONDS);
//未设置超时时间 阻塞执行
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
result.forEach(s -> System.out.println(s));
System.out.println("------------结果处理完毕,返回完毕,使用线程数量:" + threadNum);
}
}
4、
package com.redisson;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
/**
* @Description TODO
* @Date 2020/7/2 9:21
* @Author zsj
*/
public class MyCallable implements Callable {
private List list;
@Override
public List call() throws Exception {
List listReturn = Collections.synchronizedList(new ArrayList<>());
//模拟对数据处理,然后返回
for (int i = 0; i < list.size(); i++) {
listReturn.add(list.get(i) + ":处理时间:" + System.currentTimeMillis() + "---:处理线程:" + Thread.currentThread());
}
//模拟业务处理所需时间
Thread.sleep(1000);
return listReturn;
}
public void setList(List list) {
this.list = list;
}
}