有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java我可以在线程池中运行后台任务吗?

我有一个ExecutorService来同时执行我的任务。这些任务中的大多数都是简单的操作,需要约300毫秒才能完成。但其中一些任务是后台处理队列,它们始终接收新的子任务并按顺序执行。只要有正常任务在运行,这些后台任务将保持活动状态

线程池是通过一个Executors方法(还不知道是哪个)生成的,该方法具有用户指定的线程计数。我担心会发生以下情况:线程数少于后台队列数。在给定时刻,所有后台队列都在工作,阻塞了ExecutorService的所有线程。因此,不会启动任何正常任务,程序将永远挂起

这是否有可能发生,我如何避免?我在考虑一种可能性,中断后台任务,把这个地方留给正常的地方


我们的目标是限制我的应用程序中的线程数量,因为谷歌说有很多线程是不好的,让它们在大部分时间处于空闲状态也是不好的

在程序开始执行时,将在很短的时间内提交约10000个任务。大约需要50个后台任务队列,大部分时间将用于等待后台任务完成


共 (3) 个答案

  1. # 1 楼答案

    不要把长时间运行的任务和短时间运行的任务混为一谈

    使用两个池大小合适的ExecutorService实例。即使将具有长时间运行任务的后台线程的大小设置为50,池的性能也不是最佳的,因为可用的核心数(2核、4核、8核等)不在该数目之内

    我想创建两个单独的ExecutorService初始化为Runtime.getRuntime().availableProcessors()/2

    请查看下面的帖子,了解有效利用可用核心的更多细节:

    How to implement simple threading with a fixed number of worker threads

    Dynamic Thread Pool

  2. # 2 楼答案

    你可以拥有无限数量的线程,请查看cache thread pool

    Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.

    另一个选项是创建两个不同的池,并为优先任务保留一个池

  3. # 3 楼答案

    解决方案是,当没有工作时,后台任务停止而不是空闲,如果再次有足够的任务,则重新启动

    public class BackgroundQueue implements Runnable {
    
        private final ExecutorService service;
        private final Queue<Runnable> tasks = new ConcurrentLinkedQueue<>();
        private final AtomicBoolean running = new AtomicBoolean(false);
        private Future<?> future;
    
        public BackgroundQueue(ExecutorService service) {
            this.service = Objects.requireNonNull(service);
            // Create a Future that immediately returns null
            FutureTask f = new FutureTask<>(() -> null);
            f.run();
            future = f;
        }
    
        public void awaitQueueTermination() throws InterruptedException, ExecutionException {
            do {
                future.get();
            } while (!tasks.isEmpty() || running.get());
        }
    
        public synchronized void submit(Runnable task) {
            tasks.add(task);
            if (running.compareAndSet(false, true))
                future = service.submit(this);
        }
    
        @Override
        public void run() {
            while (!running.compareAndSet(tasks.isEmpty(), false)) {
                tasks.remove().run();
            }
        }
    }