Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java newFixedThreadPool的内部工作_Java_Multithreading_Concurrency - Fatal编程技术网

Java newFixedThreadPool的内部工作

Java newFixedThreadPool的内部工作,java,multithreading,concurrency,Java,Multithreading,Concurrency,请帮助我理解newFixedThreadPool(或缓存)的内部流程 当我们写下下面的陈述时, ExecutorService e=Executors.newFixedThreadPool(3) e、 执行(runaable1) e、 执行(runaable2) e、 执行(runaable3) e、 执行(runaable4) e、 执行(runaable5) 在3个execute方法之前,将创建3个线程,当调用第4个execute方法时,不会创建新线程,但工作将等待一个线程空闲 我不理解“不

请帮助我理解newFixedThreadPool(或缓存)的内部流程

当我们写下下面的陈述时, ExecutorService e=Executors.newFixedThreadPool(3)

  • e、 执行(runaable1)
  • e、 执行(runaable2)
  • e、 执行(runaable3)
  • e、 执行(runaable4)
  • e、 执行(runaable5) 在3个execute方法之前,将创建3个线程,当调用第4个execute方法时,不会创建新线程,但工作将等待一个线程空闲

    我不理解“不会创建新线程,但工作将等待线程释放”这一点。我认为当runnable1将被提供给第一个创建的线程时,一旦runnable1的run方法完成,Thread1的run也将完成,Thread1将无法调用runnable4的run方法。
    那么,java是如何用3个线程执行5个Runnable的呢将创建一个线程池,其中包含3个线程。这3个线程将用于执行在您
    e
    对象上执行的任何任务

    当您尝试通过
    ExecutorService
    执行任务时,它将被添加到任务队列中,如果池中的线程数大于任务数,则一旦有任务出现,池中的一些空闲线程将被拾取并用于执行任务

    当任务数量大于池中的线程数量时,它们将添加到队列中的pipleline中,一旦某个线程完成执行,该线程将用于从队列管道执行任务

    线程池:

    刚刚完成的线程将不会终止。请注意,它是一个线程池,所以线程是池化的,这意味着它们不会终止(通常,直到您有一些超时或其他机制),而是返回到池中,以便可以重用。这就是为什么您的第4和第5个runnable将通过这些池线程执行

    “不会创建新线程,但工作将等待线程 自由。”

    这与上面讨论的相同,然后他们将等待放在队列中,一旦某个线程完成任务执行,队列中等待的任务将被合并,并从空闲线程执行,直到队列中的所有任务都被清除为止

    由于您使用了
    newFixedThreadPool
    ,因此不会创建新线程,因此将创建一个由3个线程组成的固定线程池,它们仅用于处理到达
    ExecutorService
    特定实例的所有请求任务,在您的情况下是
    e

    其他线程池选项:
    您可以使用
    java.util.concurrent.Executors
    以多种方式创建线程池。例如,使用
    Executors#newCachedThreadPool()
    可以创建一个线程池,该线程池根据需要创建新线程,但在以前构造的线程可用时将重用这些线程。

    检查所有可用的方法,找出最适合您的方法。

    仅供参考:下面是一个非常简单的线程池实现

    class MyThreadPool implements java.util.concurrent.Executor 
    {
        private final java.util.concurrent.BlockingQueue<Runnable> queue;
    
        public MyThreadPool(int numThreads) {
            queue = new java.util.concurrent.LinkedBlockingQueue<>();
            for (int i=0 ; i<numThreads ; i++) {
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        while(true) {
                            queue.take().run();
                        }
                    }
                }).start();
            }
        }
    
        @Override
        public void execute(Runnable command) {
            queue.put(command);
        }
    }
    
    MyThreadPool类实现java.util.concurrent.Executor { 私有最终java.util.concurrent.BlockingQueue队列; 公共MyThreadPool(int numThreads){ queue=new java.util.concurrent.LinkedBlockingQueue();
    对于(int i=0;我希望您能给出响应,这里我有一个问题,如果我们看一下线程的生命周期,new->start->runnable->run->(等待,睡眠)->runnable->run->terminate,所以在执行第一个任务后,线程的状态是什么,我认为在完成执行后,线程不会是同一个线程(terminate state)可以再次用于另一个任务。@user872487,每个工作线程运行一个循环,从阻塞队列中选取新任务并运行它们。循环不会退出,除非关闭执行器。刚刚完成的线程不会终止。请注意,它是一个线程池,因此线程是池的,这意味着它们不会终止nate(通常,直到您有一些超时或其他机制)但将返回池中以便重用。这就是您的4和5次runnable将通过这些线程执行的原因。@user872487您得到答案了吗,如果没有,请写下您的答案,以便其他人可以从中受益。stackoverflow.com/help/accepted answer+1'ed.这种方法比我们有什么优势ing
    ExecutorService
    ,如果我是正确的,它在功能上是相同的???@hagrawal,我的示例不是学习以外的任何东西的方法。它仅用于说明可能不了解线程池的功能的人。我不会像在任何实际应用程序中那样使用它,因为它缺少许多有用的功能(异常处理、关闭机制、未来等等),不值得我花时间来改进它,因为java.util.concurrent中的类已经完成了我通常需要的所有操作。关于关闭如何工作,有什么提示/想法吗?@krs8888,假设您想实现
    ExecutorService
    -style
    shutdown()
    method:您可以让它设置一个标志。然后您可以更改
    execute(…)
    方法以在设置标志时引发异常,并且您可以更改工作线程的
    run()
    方法在开始每个新任务之前检查标志。如果设置了关闭标志且队列为空,则工作线程应退出。不要忘记同步对标志的访问,以便所有线程都能及时看到
    shutdown()
    请求。