我正在测试 ThreadPoolExecutor 。我在自定义的ThreadPoolExecutor的 execute()方法中打印出一些调试信息。 execute()方法由自定义 ThreadPoolExecutor 的实例调用。当我查看打印输出时,我发现有一些重复的打印输出来自主线程。我想知道为什么主 线程调用自定义的ThreadPoolExecutor的execute()方法?可运行的代码附在此处:
---------- Thead:main / 1 [PoolSize / CorePoolSize] [1/2]
---------- Thead:pool-1-thread-1/11 [PoolSize / CorePoolSize] [1/2]
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutorTest2
{
private List<MyRunnable> myRunnables = new ArrayList<>();
public static void main(String[] args)
{
new MyThreadPoolExecutorTest2().test();
}
public void test()
{
int poolSize = 2;
int maxPoolSize = 6;
int threadPoolKeepAliveTimeInSec = 30;
ExecutorService threadPoolExecutor =
new MySimpleThreadPoolExecutor2(poolSize, maxPoolSize, threadPoolKeepAliveTimeInSec);
int numOfThread = 5;
System.out.println("Start thread pool test with corePoolSize=" + poolSize + ", maxPoolSize=" + maxPoolSize
+ ", actualThreads=" + numOfThread);
for (int i = 0; i < numOfThread; i++)
{
MyRunnable tempRunnable = new MyRunnable(i + 1, "PoolTest" + (i + 1));
myRunnables.add(tempRunnable);
threadPoolExecutor.execute(tempRunnable);
}
System.out.println("********* wait for a while");
try
{
Thread.sleep(20000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("^^^^^^^^^^ shutdown them all");
for (MyRunnable runnable : myRunnables)
{
runnable.shutdown();
}
System.out.println("Ended thread pool test.");
System.exit(0);
}
public class MyRunnable implements Runnable
{
private int id = 0;
private String name = "";
private boolean shutdown = false;
public MyRunnable(int id, String name)
{
this.id = id;
this.name = name;
}
@Override
public void run()
{
System.out.println("++++ Starting Thread: " + id + ":" + name);
while (!shutdown)
{
try
{
Thread.sleep(200);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("---- Ended Thread: " + id + ":" + name);
}
public void shutdown()
{
shutdown = true;
}
}
}
class MySimpleThreadPoolExecutor2 extends ThreadPoolExecutor
{
private static int peakActiveThreads = 0;
private String taskInfo = "";
public MySimpleThreadPoolExecutor2(int nThreads, int maxThreads, int threadPoolKeepAliveTimeInSec)
{
super(nThreads, maxThreads, threadPoolKeepAliveTimeInSec * 1000L, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
System.out.println("MySimpleThreadPoolExecutor::MySimpleThreadPoolExecutor(), threadPoolSize=" + nThreads
+ ", maxThreadCount=" + maxThreads + ", threadPoolKeepAliveTimeInSec=" + threadPoolKeepAliveTimeInSec);
}
@Override
public void beforeExecute(Thread t, Runnable r)
{
int activeCount = getActiveCount();
if (MySimpleThreadPoolExecutor2.peakActiveThreads < activeCount)
{
MySimpleThreadPoolExecutor2.peakActiveThreads = activeCount;
}
taskInfo = r.toString();
String msg =
"BeforeE thread(name:id)::" + t.getName() + ":" + t.getId() + ", task::" + r.toString() + "\n"
+ threadPoolInfoStr();
System.out.println("ThreadInfo before, MySimpleThreadPoolExecutor::beforeExecute(), " + msg);
super.beforeExecute(t, r);
}
@Override
public void execute(Runnable command)
{
beforeExecute(Thread.currentThread(), command);
super.execute(command);
}
public String threadPoolInfoStr()
{
return String
.format("----------Thead: %s/%d\n[PoolSize/CorePoolSize] [%d/%d]\nActive: %d\nCompleted: %d\nTask: %d"
+ "\nisShutdown: %s\nisTerminated: %s\npeakActiveThreads: %d\nTaskInfo: %s\nQueueSize: %d----------",
Thread.currentThread().getName(), Thread.currentThread().getId(), getPoolSize(),
getCorePoolSize(), getActiveCount(), getCompletedTaskCount(), getTaskCount(), isShutdown(),
isTerminated(), MySimpleThreadPoolExecutor2.peakActiveThreads, taskInfo, getQueue().size());
}
}
答案 0 :(得分:0)
好吧,你从子类中重写的execute()方法显式调用beforeExecute:
@Override
public void execute(Runnable command)
{
beforeExecute(Thread.currentThread(), command);
super.execute(command);
}
当从客户端线程调用execute方法(在你的情况下是主线程)时,它也打印出一个调用线程的条目。然而,超级类在执行提交的任务之前从其工作线程调用beforeExecute
方法。
在给定线程中执行给定Runnable之前调用的方法。此方法由执行任务r的线程t调用,可用于重新初始化ThreadLocals或执行日志记录。
来自execute()
的显式调用是来自调用线程的额外调用。
答案 1 :(得分:-1)
我想知道为什么主线程会调用自定义的ThreadPoolExecutor的execute()方法?
因为它在代码中被明确地调用:
public static void main(String[] args) {
new MyThreadPoolExecutorTest2().test();
}
public void test() {
...
threadPoolExecutor = new MySimpleThreadPoolExecutor2();
...
threadPoolExecutor.execute(tempRunnable);
^^^^^^^
...
}