我处理了一个线程应用程序的设计,它具有以下要求:它必须具有基于一天中的时间(高峰/非高峰)运行的动态线程数。
我做了功课并研究了最好的方法,我发现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/