gpt4 book ai didi

java - ThreadPoolExecutor 没有正确收缩

转载 作者:行者123 更新时间:2023-11-30 08:56:31 27 4
gpt4 key购买 nike

我设计了一个线程应用程序,它具有以下要求:它必须具有根据一天中的时间(高峰/非高峰期)运行的动态线程数。

我做了功课并研究了执行此操作的最佳方法,我发现 java 有一个名为 ThreadPoolExecutor 的类: java.util.concurrent.ThreadPoolExecutor.ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)

这里关注的两个变量是 corePoolSize 和 maximumPoolSize,它们与 workQueue 一起充当线程池的下限和上限。调整这些值有不同的策略,如果不需要显式设置这些参数,建议使用执行器工厂方法而不是构造函数。

public class Main {
public static void main(String[] args) {
final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(0, 10, 0L, TimeUnit.MILLISECONDS, queue);
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

TimerTask task = new TimerTask() {
@Override
public void run() {
threadPool.setCorePoolSize(1);
threadPool.setMaximumPoolSize(1);
System.out.println("changed");
}
};
new Timer().schedule(task, 10000);

for (int i = 0; i < 400; i++) {
threadPool.submit(new WorkItem(i));
}
}
}

这是类似于要运行的线程的类

public class WorkItem implements Runnable {
private int workItemNumber;
private long startTime;

public WorkItem(int workItemNumber) {
this.workItemNumber = workItemNumber;
}

@Override
public void run() {
startTime = System.currentTimeMillis();
System.out.println("thread Number: " + workItemNumber + " started at: " + startTime);
while (System.currentTimeMillis() - startTime < 5000) {
}
System.out.println("WorkItem done: " + workItemNumber);
}
}

但是,查看日志,执行的线程数保持不变,没有变化。

最佳答案

您的代码完全按照您的预期运行。启动并运行了 10 个线程,并排队了 100 个线程。那时,您的主线程(一个排队线程)被阻塞队列阻塞。然后您的计时器将可用线程更改为 1,这意味着您的队列处理速度更慢。然而,您所看到的是,因为您的线程必须等待超过 10 秒才能实际执行,所以它们会立即完成。尝试对您的代码进行以下更改:

public class WorkItem implements Runnable {
private long startTime;
private long runTime;
private int workItemNumber;

public WorkItem(long startTime, int workItemNumber) {
this.startTime = startTime;
this.workItemNumber= workItemNumber;
}

@Override
public void run() {
System.out.println("WorkItem started: " + workItemNumber + " Queued at: " + startTime);
runTime = System.currentTimeMillis();
while (System.currentTimeMillis() - runTime < 10000) {
}
System.out.println("WorkItem done: " + workItemNumber);
}
}

这会让您看到执行情况如您所愿。在核心池设置为 0 的情况下使用数组阻塞队列的奇怪之处在于它只会启动一个线程,然后填满队列,然后启动更多线程(最大池大小)。如果您对排队代码进行细微更改,就会看到这种情况。

for (int i = 1; i < 101; i++) {
threadPool.submit(new WorkItem(System.currentTimeMillis(), i));
}

for (int i = 101; i < 401; i++) {
long thisTime = System.currentTimeMillis();
threadPool.submit(new WorkItem(System.currentTimeMillis(), i));
while (System.currentTimeMillis() - thisTime < 500) {

}
}

关于java - ThreadPoolExecutor 没有正确收缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28567238/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com