Java 简明教程

Java - Thread Pools

Thread Pools

线程池是预初始化的 threads 集合。线程池背后的总体计划是在方法启动时形成各种线程,并将它们放入池中,它们在池中等待工作。一旦服务器收到参与请求,便会唤醒此池中的一个线程(如果可用),并向它传递服务请求。一旦线程完成服务,它便会返回池中,等待更多工作。如果池中没有可访问的线程,则服务器会等待,直到一个线程变为可用。

A thread pool is a collection of pre-initialized threads. The general plan behind a thread pool is to form variety of threads at method startup and place them into a pool, wherever they sit and expect work. once a server receives a call for participation, it awakens a thread from this pool−if one is available−and passes it the request for service. Once the thread completes its service, it returns to the pool and awaits a lot of work. If the pool contains no accessible thread, the server waits till one becomes free.

Why Use Thread Pools in Java?

  1. It saves time as a result of there’s no need to produce new thread.

  2. It is utilized in Servlet and JSP wherever instrumentality creates a thread pool to method the request.

Creating Thread Pools in Java

Java 提供了*java.util.concurrent.Executors*类,它提供了一些方法来创建线程池。

Java provides a java.util.concurrent.Executors class provides couple of methods to create a thread pools.

Executors Class Methods

以下是此类中创建线程池的一些重要且有用的方法:

Following are few important and useful methods this class to create Thread Pools -

Sr.No.

Method & Description

1

public static ExecutorService newCachedThreadPool() Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.

2

public static ExecutorService newFixedThreadPool(int nThreads) Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.

3

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.

4

public static ExecutorService newWorkStealingPool() Creates a work-stealing thread pool using all available processors as its target parallelism level.

Creating a Thread Pool Using newFixedThreadPool() Method

可变线程池通过调用 Executor 类的新建 static newFixedThreadPool() 方法获得。

A fixed thread pool obtainted by calling the static newFixedThreadPool() method of Executors class.

Syntax

ExecutorService fixedPool = Executors.newFixedThreadPool(2);

其中,

Where,

  1. Maximum 2 threads will be active to process tasks.

  2. If more than 2 threads are submitted then they are held in a queue until threads become available.

  3. A new thread is created to take its place if a thread terminates due to failure during execution shutdown on executor is not yet called.

  4. Any thread exists till the pool is shutdown.

Example: Creating a Thread Pool Using newFixedThreadPool() Method

下面的 TestThread 程序演示了使用 Execution 的 newFixedThreadPool() 方法来创建包含两个线程的线程池。我们正在使用 ThreadPoolExecutor 对象,并用 newFixedThreadPool(2) 初始化,一个大小为 2 的固定线程池。然后我们正在打印线程池的各种属性。然后我们向执行器中添加一些线程,然后打印线程池的相同属性以反映更改。

The following TestThread program shows usage of Executors newFixedThreadPool() method to create a thread pool of two threads. We’re using a ThreadPoolExecutor object and initialized with newFixedThreadPool(2), a fix thread pool of size 2. Then we’re printing various attributes of the threadpool. Then we’re adding few threads to the executor and then same attributes of threadpool are printed to reflect the changes.

package com.tutorialspoint;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThread {

   public static void main(final String[] arguments) throws InterruptedException {
      ExecutorService executor = Executors.newFixedThreadPool(2);

      // Cast the object to its class type
      ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

      //Stats before tasks execution
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.submit(new Task());
      executor.submit(new Task());
	  executor.submit(new Task());
      executor.submit(new Task());

      //Stats after tasks execution
      System.out.println("Core threads: " + pool.getCorePoolSize());
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.shutdown();
   }

   static class Task implements Runnable {

      public void run() {

         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
               TimeUnit.SECONDS.sleep(duration);

            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}
Largest executions: 0
Maximum allowed threads: 2
Current threads in pool: 0
Currently executing threads: 0
Total number of threads(ever scheduled): 0
Core threads: 2
Largest executions: 2
Maximum allowed threads: 2
Current threads in pool: 2
Currently executing threads: 2
Total number of threads(ever scheduled): 4
Running Task! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1

尽管在这里我们提交了四次线程,但只执行了两个线程,因为线程池被固定为仅接受两个线程。

Here although, we’ve submitted four threads but only two threads are executed as ThreadPool is fixed to accept only two threads.

Creating a Thread Pool Using newCachedThreadPool() Method

可以通过调用 Executors 类的静态 newCachedThreadPool() 方法获得缓存的线程池。

A cached thread pool obtainted by calling the static newCachedThreadPool() method of Executors class.

Syntax

ExecutorService executor = Executors.newCachedThreadPool();

其中,

Where,

  1. newCachedThreadPool method creates an executor having an expandable thread pool.

  2. Such an executor is suitable for applications that launch many short-lived tasks.

Example: Creating a Thread Pool Using newCachedThreadPool() Method

TestThread 程序展示了 Executor newCachedThreadPool() 方法的使用,它用来创建一个可扩展的线程池。我们使用了 ThreadPoolExecutor 对象,并使用 newCachedThreadPool() 初始化。然后,我们将打印线程池的各种属性。然后,我们向执行器添加几个线程,接着打印线程池的相同属性以反映更改。

The following TestThread program shows usage of Executors newCachedThreadPool() method to create a expandable thread pool of threads. We’re using a ThreadPoolExecutor object and initialized with newCachedThreadPool(). Then we’re printing various attributes of the threadpool. Then we’re adding few threads to the executor and then same attributes of threadpool are printed to reflect the changes.

package com.tutorialspoint;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThread {

   public static void main(final String[] arguments) throws InterruptedException {
      ExecutorService executor = Executors.newCachedThreadPool();

      // Cast the object to its class type
      ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

      //Stats before tasks execution
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.submit(new Task());
      executor.submit(new Task());
	  executor.submit(new Task());
      executor.submit(new Task());

      //Stats after tasks execution
      System.out.println("Core threads: " + pool.getCorePoolSize());
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.shutdown();
   }

   static class Task implements Runnable {

      public void run() {

         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
               TimeUnit.SECONDS.sleep(duration);

            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}
Largest executions: 0
Maximum allowed threads: 2147483647
Current threads in pool: 0
Currently executing threads: 0
Total number of threads(ever scheduled): 0
Core threads: 0
Largest executions: 4
Maximum allowed threads: 2147483647
Current threads in pool: 4
Currently executing threads: 4
Total number of threads(ever scheduled): 4
Running Task! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-4
Running Task! Thread Name: pool-1-thread-3
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-3
Task Completed! Thread Name: pool-1-thread-4
Task Completed! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1

Creating a Thread Pool Using newScheduledThreadPool() Method

通过调用 Executor 类的静态 newScheduledThreadPool() 方法获取一个计划线程池。

A scheduled thread pool obtainted by calling the static newScheduledThreadPool() method of Executors class.

Syntax

ExecutorService executor = Executors.newScheduledThreadPool(1);

Example: Creating a Thread Pool Using newScheduledThreadPool() Method

TestThread 程序演示了 Executor newScheduledThreadPool() 方法的使用,它用来创建一个线程池。我们使用了一个 ScheduledExecutorService 对象作为计划程序,并使用 newScheduledThreadPool() 进行了初始化。我们还创建了一个 ScheduledFuture 对象,以计划在延迟两秒之后每两秒执行一次任务。使用计划程序,我们将任务计划为连续运行十秒。

The following TestThread program shows usage of Executors newScheduledThreadPool() method to create a thread pool of a thread. We’re using a ScheduledExecutorService object as scheduler and initialized with newScheduledThreadPool(). We’ve created a ScheduledFuture object to schedule a task to execute every two seconds after an initial delay of two seconds. Using scheduler, we scheduled the task to run for ten seconds.

package com.tutorialspoint;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class TestThread {

   public static void main(final String[] arguments) throws InterruptedException {
      final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

      final ScheduledFuture<?> beepHandler =
         scheduler.scheduleAtFixedRate(new BeepTask(), 2, 2, TimeUnit.SECONDS);

      scheduler.schedule(new Runnable() {

         @Override
         public void run() {
            beepHandler.cancel(true);
            scheduler.shutdown();
         }
      }, 10, TimeUnit.SECONDS);
   }

   static class BeepTask implements Runnable {

      public void run() {
         System.out.println("beep");
      }
   }
}
beep
beep
beep
beep
beep