guava多线程,futurecallback线程调用不平均

最近查看日志,发现guava的多个futurecallback线程调用不平均,在这里记录一下

Guava Futures简介

Google Guava框架的 com.google.common.util.concurrent包是并发相关的包,它是对JDK自带
concurrent包中Future和线程池相关类的扩展,从而衍生出一些新类,并提供了更为广泛的功能。
在项目中常用的该包中类如下所示:

  • ListenableFuture:该接口扩展了Future接口,增加了addListener方法,该方法在给定的excutor上注册一个监听器,当计算完成时会马上调用该监听器。不能够确保监听器执行的顺序,但可以在计算完成时确保马上被调用。
  • FutureCallback:该接口提供了OnSuccess和onFailure方法。获取异步计算的结果并回调。
  • MoreExecutors:该类是final类型的工具类,提供了很多静态方法。例如listeningDecorator方法初始化ListeningExecutorService方法,使用此实例submit方法即可初始化ListenableFuture对象。
  • ListenableFutureTask:该类是一个适配器,可以将其它Future适配成ListenableFuture。
  • ListeningExecutorService:该类是对ExecutorService的扩展,重写了ExecutorService类中的submit方法,并返回ListenableFuture对象。
  • JdkFutureAdapters:该类扩展了FutureTask类并实现ListenableFuture接口,增加了addListener方法。
  • Futures:该类提供和很多实用的静态方法以供使用。

现象

我创建了8个线程,平均处理多任务,但是到最后发现futurecallback调用的线程分部不平均。

日志:

2022-06-10 16:49:23.402 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=4%
2022-06-10 16:49:23.402 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=8%
2022-06-10 16:49:23.402 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=12%
2022-06-10 16:49:23.407 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=16%
2022-06-10 16:49:23.407 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=20%
2022-06-10 16:49:23.409 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=24%
2022-06-10 16:49:23.409 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=28%
2022-06-10 16:49:23.409 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=32%
2022-06-10 16:49:23.411 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=36%
2022-06-10 16:49:23.411 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=40%
2022-06-10 16:49:23.413 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=44%
2022-06-10 16:49:23.413 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=48%
2022-06-10 16:49:23.413 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=52%
2022-06-10 16:49:23.416 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=56%
2022-06-10 16:49:23.416 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=60%
2022-06-10 16:49:23.418 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=64%
2022-06-10 16:49:23.418 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=68%
2022-06-10 16:49:23.418 [pool-7-thread-7] INFO  c.l.AsyncTask - percent=72%

2022-06-10 16:49:25.231 [pool-7-thread-8] INFO  c.l.AsyncTask - percent=76%
2022-06-10 16:49:27.436 [pool-7-thread-2] INFO  c.l.AsyncTask - percent=80%
2022-06-10 16:49:27.970 [pool-7-thread-4] INFO  c.l.AsyncTask - percent=84%
2022-06-10 16:49:31.812 [pool-7-thread-5] INFO  c.l.AsyncTask - percent=88%
2022-06-10 16:49:33.475 [pool-7-thread-6] INFO  c.l.AsyncTask - percent=92%
2022-06-10 16:49:34.184 [pool-7-thread-3] INFO  c.l.AsyncTask - percent=96%
2022-06-10 16:56:56.214 [pool-7-thread-1] INFO  c.l.AsyncTask - percent=100%

参考例子:

ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(false);
        return t;
    }
});
ListenableFuture<?> listenableFuture = JdkFutureAdapters.listenInPoolThread(
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("run!!!");
            }
        }),
        executorService
);
Futures.addCallback(listenableFuture, new FutureCallback<Object>() {

    @Override
    public void onSuccess(@Nullable Object result) {
        System.out.println("onSuccess");
    }

    @Override
    public void onFailure(Throwable t) {
        System.out.println("onFailure");
    }
});

参考

java - how Futures.addCallback guarantee the callback to be executed at the thread executing the future task? - Stack Overflow

Futures (Guava: Google Core Libraries for Java 23.0 API)

https://stackoverflow.com/questions/35211331/in-which-thread-futurecallback-will-be-called-for-a-listenablefuture-in-guava

https://stackoverflow.com/questions/63629421/listenable-future-callback-is-heavily-delayed

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
LoadingCache是Guava库中的一个缓存工具类,用于高效地缓存数据。在多线程应用中,LoadingCache可以提供良好的并发支持。 首先,LoadingCache的内部实现是线程安全的。它使用了并发集合ConcurrentMap作为缓存的存储结构,并使用了同步机制来保证多线程并发的正确性。因此,在多线程环境下,不需要额外的加锁操作,不需要开发人员手动处理并发访问问题,而是由LoadingCache自身来处理。 其次,LoadingCache提供了get和getAll方法来获取缓存中的数据。在多线程应用中,当多个线程同时调用get方法来获取缓存中的数据时,LoadingCache可以保证只有一个线程去加载数据,其他线程会等待加载完成后直接从缓存中获取数据,避免了重复的数据加载操作。 另外,LoadingCache还提供了refresh方法,用于定时刷新缓存中的数据。在多线程应用中,可以通过设置定时任务或者使用定时调度框架,定期调用refresh方法来刷新缓存中的数据。这样可以保证在多线程并发操作下,缓存的数据始终是最新的。 需要注意的是,在多线程应用中,如果缓存的数据更新频繁,而且有多个线程在同时操作缓存,可能会导致缓存的命中率下降。这时可以考虑使用更加高级的缓存方案,如分布式缓存,来进一步提升缓存的并发性能和命中率。 综上所述,LoadingCache在多线程应用中可以提供良好的并发支持。它的线程安全的内部实现、合理的并发控制机制,以及定时刷新的功能,使得在多线程并发访问下,能够高效地缓存和获取数据,并保证数据的一致性和可靠性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值