簡體   English   中英

為什么主線程還要調用線程池的execute()方法?

[英]why main thread is also call the thread pool's execute() method?

我正在測試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());
    }
}

好吧,您從子類中重寫的 execute() 方法顯式調用 beforeExecute :

@Override
public void execute(Runnable command)
{
    beforeExecute(Thread.currentThread(), command);
    super.execute(command);
}

由於從客戶端線程(在您的情況下是主線程)調用 execute 方法,它也會打印出調用線程的條目。 然而,在執行提交的任務之前,超類從其工作線程調用beforeExecute方法。

注意beforeExecutejavadoc

在給定線程中執行給定 Runnable 之前調用的方法。 此方法由將執行任務 r 的線程 t 調用,並可用於重新初始化 ThreadLocals 或執行日志記錄。

來自execute()顯式調用是來自調用線程的額外調用。

我想知道為什么主線程調用自定義的ThreadPoolExecutor的execute()方法?

因為它在代碼中被明確調用:

public static void main(String[] args) {
    new MyThreadPoolExecutorTest2().test();
}

public void test() {
   ...
   threadPoolExecutor = new MySimpleThreadPoolExecutor2();
   ...
       threadPoolExecutor.execute(tempRunnable);
                          ^^^^^^^
   ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM