【问题标题】:How do you limit threads in the ExecutorService?如何限制 ExecutorService 中的线程?
【发布时间】:2013-08-08 06:21:34
【问题描述】:

我使用 ExecutorService 在不同的线程中运行许多任务。 有时,线程池中等待的 Runnable 实例过多可能会导致 Out Of Memory 问题。

我尝试编写一个阻塞作业执行器来解决它。有没有官方的解决方案?

例如:

    BlockingJobExecutor executor = new BlockingJobExecutor(3);
    for (int i = 0; i < 1000; i++) {
        executor.addJob(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                LogFactory.getLog(BTest.class).info("test " + System.currentTimeMillis());
            }
        });
    }
    executor.shutdown();

这里是 BlockingJobExecutor 类:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class BlockingJobExecutor {

    AtomicInteger counter = new AtomicInteger();
    ExecutorService service;
    int threads;

    public BlockingJobExecutor(int threads) {
        if (threads < 1) {
            throw new IllegalArgumentException("threads must be greater than 1.");
        }
        service = Executors.newFixedThreadPool(threads);
        this.threads = threads;
    }

    static class JobWrapper implements Runnable {
        BlockingJobExecutor executor;
        Runnable job;

        public JobWrapper(BlockingJobExecutor executor, Runnable job) throws InterruptedException {
            synchronized (executor.counter) {
                while (executor.counter.get() >= executor.limit()) {
                    executor.counter.wait();
                }
            }
            this.executor = executor;
            this.job = job;
        }

        @Override
        public void run() {
            try {
                job.run();
            } finally {
                synchronized (executor.counter) {
                    executor.counter.decrementAndGet();
                    executor.counter.notifyAll();
                }
            }
        }
    }

    public int limit() {
        return threads;
    }

    public void shutdown() {
        service.shutdown();
        try {
            service.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void addJob(Runnable job) {
        try {
            service.execute(new JobWrapper(this, job));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}

【问题讨论】:

  • 你的意思是你有太多的作业等待运行,还是你有太多的线程同时存在?
  • 等待运行的作业太多。

标签: java multithreading executorservice


【解决方案1】:

发生这种情况的方式有两种。您可能有太多的可运行对象排队等待运行,或者同时运行的线程太多。如果排队的作业太多,可以使用ExecutorService中固定大小的BlockingQueue来限制可以排队的项目数。然后,当您尝试将新任务排队时,该操作将阻塞,直到队列中有空间为止。

如果一次运行的线程太多,您可以通过调用 Executors.newFixedThreadPool 来限制 ExecutorService 中可用于运行任务的线程数。

【讨论】:

    猜你喜欢
    • 2019-03-15
    • 2011-06-16
    • 2014-08-01
    • 2011-09-01
    • 1970-01-01
    • 2011-08-22
    • 2020-02-22
    • 1970-01-01
    • 2010-09-09
    相关资源
    最近更新 更多