ExecutorService和AtomicInteger:RejectedExecutionException

时间:2018-11-14 01:10:07

标签: java executorservice atomicinteger

我希望atomicInteger的值为100,然后程序终止

 public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        AtomicInteger atomicInteger = new AtomicInteger(0);
        do {
            executor.submit(() -> {
                System.out.println(atomicInteger.getAndAdd(10));
                if (atomicInteger.get() == 100) {
                    //executor.shutdownNown();
                }
            });
        } while (true);
    }

我有错

Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1d8d10a rejected from java.util.concurrent.ThreadPoolExecutor@9e54c2[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 10]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1374)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at java.util.concurrent.Executors$DelegatedExecutorService.submit(Executors.java:678)

我应该如何实施。

2 个答案:

答案 0 :(得分:0)

您应该只更改while循环以检查所需条件,然后关闭执行程序

答案 1 :(得分:0)

这里不需要使用AtomicInteger,因为可以保证Runnable lambda函数调用可以按顺序执行(通过新的SingleThreadExecutor)。另外,您的Runnable lambda代码需要花费任何时间来执行(例如2毫秒),您的主循环将排队超过10个达到极限所需的任务。如果您在Runnable lambda函数中添加2ms睡眠,并在do / while循环中添加一个计数器,并在最后打印出计数器的值,以查看您排队了多少个Runnable实例,则会看到这种情况。

假设您希望使用并发线程测试此代码,则需要用newFixedThreadPool替换对newSingleThreadPool的调用。当使用并发线程时,您的代码采用的方法会出现问题。在下面的代码中,我已切换到newFixedThreadPool,添加了一个计数器,因此我们可以看到已排队的任务数量,并添加到Runnable lambda函数的短暂暂停中,仅代表少量工作。当我执行此程序时,atomicInteger变得大于13000,并且程序崩溃,并出现 java.lang.OutOfMemoryError:超出了GC开销限制,这是因为,无论当前值是什么,您的可运行函数总是将10添加到atomicInteger 。而且,代码将更多的任务排队。这是带有这些小的更改的代码,它们说明了问题。

public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(3);
    AtomicInteger atomicInteger = new AtomicInteger(0);
    int i=0;
    do {
        executor.submit(() -> {
            pause(2); // simulates some small amount of work.
            System.out.println("atomicInt="+atomicInteger.getAndAdd(10));
            pause(2); // simulates some small amount of work.
            if (atomicInteger.get() == 100) {
                System.out.println("executor.shutdownNow()");
                System.out.flush();
                executor.shutdownNow();
            }
        });
        if (atomicInteger.get() == 100) {
            break;
        }
    } while (true);
    System.out.println("final atomicInt="+atomicInteger.get());
    System.out.println("final tasks queued="+i);
}
public static void pause(long millis) {
    try {
        Thread.sleep(millis);
    } catch (InterruptedException ex) {
    }
}

这是一个解决并发问题并将执行者管理移出它实际上不属于的工作线程的版本:

private static int LIMIT = 100;
private static int INCREMENT = 10;

public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    AtomicInteger atomicInteger = new AtomicInteger(0);
    for (int i=0; i < LIMIT/INCREMENT; i++) {
            executor.submit(() -> {
                pause(2);
                System.out.println("atomicInt=" + atomicInteger.getAndAdd(INCREMENT));
                System.out.flush();
                pause(2);
            });
    }
    executor.shutdown();
    while (!executor.isTerminated()) {
        System.out.println("Executor not yet terminated");
        System.out.flush();
        pause(4);
    }
    System.out.println("final atomicInt=" + atomicInteger.get());
}

public static void pause(long millis) {
    try {
        Thread.sleep(millis);
    } catch (InterruptedException ex) {

    }
}