Java 简明教程
Java - Thread Pools
Thread Pools
线程池是预初始化的 threads 集合。线程池背后的总体计划是在方法启动时形成各种线程,并将它们放入池中,它们在池中等待工作。一旦服务器收到参与请求,便会唤醒此池中的一个线程(如果可用),并向它传递服务请求。一旦线程完成服务,它便会返回池中,等待更多工作。如果池中没有可访问的线程,则服务器会等待,直到一个线程变为可用。
Creating Thread Pools in Java
Java 提供了*java.util.concurrent.Executors*类,它提供了一些方法来创建线程池。
Executors Class Methods
以下是此类中创建线程池的一些重要且有用的方法:
Sr.No. |
Method & Description |
1 |
public static ExecutorService newCachedThreadPool() 根据需要创建新线程的线程池,但当先前构造的线程可用时会重用这些线程。 |
2 |
public static ExecutorService newFixedThreadPool(int nThreads) 创建重用固定数量线程的线程池,并且这些线程从共享的无界队列中运行。 |
3 |
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 创建线程池,该线程池可安排命令在给定的延迟后或定期执行。 |
4 |
public static ExecutorService newWorkStealingPool() 创建工作窃取线程池,使用所有可用处理器作为其目标并行级别。 |
Creating a Thread Pool Using newFixedThreadPool() Method
可变线程池通过调用 Executor 类的新建 static newFixedThreadPool() 方法获得。
Syntax
ExecutorService fixedPool = Executors.newFixedThreadPool(2);
其中,
-
最多有 2 个线程激活以处理任务。
-
如果提交的线程超过 2 个,则将它们保存在队列中,直到线程变为可用。
-
如果线程因为执行期间的故障而终止,则会创建新线程以取代它(尚未调用执行器的关闭)。
-
任何线程在池关闭之前都会存在。
Example: Creating a Thread Pool Using newFixedThreadPool() Method
下面的 TestThread 程序演示了使用 Execution 的 newFixedThreadPool() 方法来创建包含两个线程的线程池。我们正在使用 ThreadPoolExecutor 对象,并用 newFixedThreadPool(2) 初始化,一个大小为 2 的固定线程池。然后我们正在打印线程池的各种属性。然后我们向执行器中添加一些线程,然后打印线程池的相同属性以反映更改。
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
尽管在这里我们提交了四次线程,但只执行了两个线程,因为线程池被固定为仅接受两个线程。
Creating a Thread Pool Using newCachedThreadPool() Method
可以通过调用 Executors 类的静态 newCachedThreadPool() 方法获得缓存的线程池。
Syntax
ExecutorService executor = Executors.newCachedThreadPool();
其中,
-
newCachedThreadPool 方法创建拥有可扩展线程池的执行器。
-
这种执行器适合于启动许多短生存期任务的应用程序。
Example: Creating a Thread Pool Using newCachedThreadPool() Method
TestThread 程序展示了 Executor newCachedThreadPool() 方法的使用,它用来创建一个可扩展的线程池。我们使用了 ThreadPoolExecutor 对象,并使用 newCachedThreadPool() 初始化。然后,我们将打印线程池的各种属性。然后,我们向执行器添加几个线程,接着打印线程池的相同属性以反映更改。
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() 方法获取一个计划线程池。
Example: Creating a Thread Pool Using newScheduledThreadPool() Method
TestThread 程序演示了 Executor newScheduledThreadPool() 方法的使用,它用来创建一个线程池。我们使用了一个 ScheduledExecutorService 对象作为计划程序,并使用 newScheduledThreadPool() 进行了初始化。我们还创建了一个 ScheduledFuture 对象,以计划在延迟两秒之后每两秒执行一次任务。使用计划程序,我们将任务计划为连续运行十秒。
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