在这篇文章中,我们将结合实例讨论重要的并发效用执行器类。我们将在例子中使用Java 8 Lambda表达式。
Executors类为本包中定义的Executor、ExecutorService、ScheduledExecutorService、ThreadFactory和Callable类提供工厂和实用方法。
该类支持以下种类的方法。
在这篇文章中,我们将结合实例讨论Executors类的五个重要的实用方法。
创建一个线程池,重用固定数量的线程在一个共享的无界队列中运行。在任何时候,最多只有nThreads
个线程在处理任务。如果在所有线程都处于活动状态时提交了额外的任务,它们将在队列中等待,直到有线程可用。如果任何线程在关机前的执行过程中因故障而终止,如果需要执行后续任务,将有一个新的线程取代它的位置。池中的线程将存在,直到它被明确关闭。
**参数。 **nThreads 池中线程的数量
返回:新创建的线程池
抛出。 IllegalArgumentException - 如果nThreads <= 0
语法:
ExecutorService executorService = Executors.newFixedThreadPool(noOfThreads);
让我们创建一个非常简单的例子。
第一步:创建一个名为 "Task.java "的Runnable
任务。
class Task implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
try {
Thread.sleep(200);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
}
第2步:让我们创建newFixedThreadPool()
方法,用两个线程执行5个任务。
public class FixedThreadPoolExample {
public static void main(final String[] args) throws InterruptedException, ExecutionException {
System.out.println("Thread main started");
final ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new Task());
executorService.execute(new Task());
executorService.execute(new Task());
executorService.execute(new Task());
executorService.execute(new Task());
executorService.shutdown();
System.out.println("Thread main finished");
}
}
输出。
Thread main started
[pool-1-thread-1] Message 0
[pool-1-thread-2] Message 0
Thread main finished
[pool-1-thread-1] Message 1
[pool-1-thread-2] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-2] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-2] Message 3
[pool-1-thread-2] Message 4
[pool-1-thread-1] Message 4
[pool-1-thread-1] Message 0
[pool-1-thread-2] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-2] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-2] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-2] Message 3
[pool-1-thread-1] Message 4
[pool-1-thread-2] Message 4
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
我们使用了新的newFixedThreadPool
,所以当我们提交了5个任务后,将创建2个新的线程并执行2个任务。其他3个任务将在一个等待队列中等待。只要一个线程完成了任何任务,另一个任务就会被这个线程选中并执行。
这个方法创建了一个Executor
,它使用一个单一的工作线程,从一个无界队列中操作。(但是请注意,如果这个单线程在关机前的执行过程中由于故障而终止,如果需要执行后续的任务,一个新的线程将取代它的位置。) 任务被保证按顺序执行,并且在任何时候都不会有超过一个任务处于活动状态。与其他同等的newFixedThreadPool(1)
不同,返回的执行器被保证不能被重新配置以使用额外的线程。
请注意,Executors.newSingleThreadExecutor()
方法返回新创建的单线程执行器。
语法。
ExecutorService executorService = Executors.newSingleThreadExecutor();
在这个例子中,我们用一个单线程实例化了一个线程池。所有的任务都由同一个线程按顺序执行。
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
//*
/* Instantiates a thread pool with a single thread
/* All tasks are executed sequentially by the same thread
/*/
public class SingleThreadPoolExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Thread main started");
Runnable task1 = () -> {
System.out.println("Executing Task1 inside : " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
};
Runnable task2 = () -> {
System.out.println("Executing Task2 inside : " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
};
Runnable task3 = () -> {
System.out.println("Executing Task3 inside : " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
};
final ExecutorService executorService = Executors.newSingleThreadExecutor();
System.out.println("Submitting the tasks for execution...");
executorService.submit(task1);
executorService.submit(task2);
executorService.submit(task3);
executorService.shutdown();
System.out.println("Thread main finished");
}
}
输出:
Thread main started
Submitting the tasks for execution...
Executing Task1 inside : pool-1-thread-1
Thread main finished
Executing Task2 inside : pool-1-thread-1
Executing Task3 inside : pool-1-thread-1
我们使用了newSingleThreadExecutor
,所以当我们提交了3个任务后,将创建一个新的线程,并一次执行一个任务。其他两个任务将在一个等待队列中等待。一旦一个线程完成了一个任务,另一个任务就会被这个线程选中并执行。
这个方法创建了一个线程池,它可以根据需要创建新的线程,但当之前构建的线程可用时,它将重新使用。这些线程池通常会提高执行许多短暂的异步任务的程序的性能。
对执行的调用将重用先前构建的线程,如果可用的话。如果没有现有的线程可用,将创建一个新的线程并添加到池中。六十秒内未被使用的线程将被终止并从缓存中删除。因此,一个池子如果保持足够长的空闲时间,就不会消耗任何资源。请注意,具有类似属性但细节不同(例如,超时参数)的池可以使用ThreadPoolExecutor
构造函数来创建。
语法。
final ExecutorService executorService = Executors.newCachedThreadPool();
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CachedThreadPoolExample {
public static void main(final String[] args) throws InterruptedException, ExecutionException {
System.out.println("Thread main started");
Runnable task1 = () -> {
System.out.println("Executing Task1 inside : " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
};
Runnable task2 = () -> {
System.out.println("Executing Task2 inside : " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
};
Runnable task3 = () -> {
System.out.println("Executing Task3 inside : " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ex) {
throw new IllegalStateException(ex);
}
};
final ExecutorService executorService = Executors.newCachedThreadPool();
System.out.println("Submitting the tasks for execution...");
executorService.submit(task1);
executorService.submit(task2);
executorService.submit(task3);
executorService.shutdown();
System.out.println("Thread main finished");
}
}
输出。
Thread main started
Submitting the tasks for execution...
Executing Task1 inside : pool-1-thread-1
Executing Task3 inside : pool-1-thread-3
Executing Task2 inside : pool-1-thread-2
Thread main finished
该方法创建了一个线程池,可以安排命令在给定的延迟后运行或定期执行。
newScheduledThreadPool方法返回ScheduledExecutorService
接口ScheduledExecutorService
接口提供 schedule()
方法创建具有各种延迟的任务,并返回一个可用于取消或检查执行的任务对象。scheduleAtFixedRate()
和scheduleWithFixedDelay()
方法创建并执行周期性运行的任务,直到取消。
使用Executor.execute(Runnable)
和ExecutorService
提交方法提交的命令以要求的延迟为零来安排。在schedule方法中也允许零和负延迟(但不是周期),并被视为立即执行的请求。
让我们通过一个例子来理解ScheduledExecutorService
界面和newScheduledThreadPool()
工厂方法的方法。
public class SchedulingTasksWithScheduledThreadPool {
public static void main(String[] args) throws InterruptedException {
System.out.println("Thread main started");
// Create a task
Runnable task1 = () -> {
System.out.println("Executing the task1 at: " + new Date());
};
// Create a task
Runnable task2 = () -> {
System.out.println("Executing the task2 at: " + new Date());
};
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
System.out.println("Scheduling task to run after 5 seconds... " + new Date());
scheduledExecutorService.schedule(task1, 5, TimeUnit.SECONDS);
scheduledExecutorService.schedule(task2, 5, TimeUnit.SECONDS);
scheduledExecutorService.shutdown();
System.out.println("Thread main finished");
}
}
输出:
Thread main started
Scheduling task to run after 5 seconds... Sat Sep 01 10:56:40 IST 2018
Thread main finished
Executing the task1 at: Sat Sep 01 10:56:45 IST 2018
Executing the task2 at: Sat Sep 01 10:56:45 IST 2018
*scheduledExecutorService.schedule()*函数接收一个Runnable,一个延迟值,以及延迟的单位。上面的程序在提交后的5秒后执行任务。
现在让我们看一个例子,我们定期执行任务 -
public class SchedulingTasksWithScheduledThreadPool {
public static void main(String[] args) throws InterruptedException {
System.out.println("Thread main started");
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// Create a task
Runnable task1 = () -> {
System.out.println("Executing the task1 at: " + new Date());
};
scheduledExecutorService.scheduleAtFixedRate(task1, 0, 2, TimeUnit.SECONDS);
System.out.println("Thread main finished");
}
}
输出:
Thread main started
Thread main finished
Executing the task1 at: Sat Sep 01 11:03:16 IST 2018
Executing the task1 at: Sat Sep 01 11:03:18 IST 2018
Executing the task1 at: Sat Sep 01 11:03:20 IST 2018
Executing the task1 at: Sat Sep 01 11:03:22 IST 2018
Executing the task1 at: Sat Sep 01 11:03:24 IST 2018
......
注意,如果任务遇到异常,任务的后续执行会被抑制。否则,只有当你关闭执行器或杀死程序时,该任务才会终止。
这个方法创建了一个单线程的执行器,它可以安排命令在给定的延迟后运行或定期执行。(但是请注意,如果这个单线程在关机前的执行过程中由于故障而终止,如果需要执行后续的任务,一个新的线程将取代它的位置。) 任务被保证按顺序执行,并且在任何时候都不会有超过一个任务处于活动状态。与其他相等的newScheduledThreadPool(1)不同,返回的执行器被保证不能被重新配置以使用额外的线程。
语法。
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ExecutorsDemo {
public static void main(String[] args) {
ExecutorsDemo demo = new ExecutorsDemo();
demo.newSingleThreadScheduledExecutor();
}
private void newSingleThreadScheduledExecutor() {
System.out.println("Thread main started");
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
// Create a task
Runnable task1 = () -> {
System.out.println("Executing the task1 at: " + new Date());
};
scheduledExecutorService.scheduleAtFixedRate(task1, 0, 2, TimeUnit.SECONDS);
System.out.println("Thread main finished");
}
}
输出。
Thread main started
Thread main finished
Executing the task1 at: Mon Sep 10 13:15:57 IST 2018
Executing the task1 at: Mon Sep 10 13:15:59 IST 2018
Executing the task1 at: Mon Sep 10 13:16:01 IST 2018
Executing the task1 at: Mon Sep 10 13:16:03 IST 2018
Executing the task1 at: Mon Sep 10 13:16:05 IST 2018
Executing the task1 at: Mon Sep 10 13:16:07 IST 2018
...............
在Java多线程教程中学习多线程在Java并发性教程中学习高级并发性
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.javaguides.net/2018/09/executors-utility-class-in-java.html
内容来源于网络,如有侵权,请联系作者删除!