参考: http://www.open-open.com/bbs/view/1320131360999
我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,而当针对高质量Java多线程并发程序设计时,为防止死蹦等现象的出现,比如使用java之前的wait()、notify()和synchronized等,每每需要考虑性能、死锁、公平性、资源管理以及如何避免线程安全性方面带来的危害等诸多因素,往往会采用一些较为复杂的安全策略,加重了程序员的开发负担.万幸的是,在JDK1.5出现之后,Sun大神终于为我们这些可怜的小程序员推出了java.util.concurrent工具包以简化并发完成。开发者们借助于此,将有效的减少竞争条件(race conditions)和死锁线程。concurrent包很好的解决了这些问题,为我们提供了更实用的并发程序模型。
java.util.concurrent下主要的接口和类:
Executor:具体Runnable任务的执行者。
ExecutorService:一个线程池管理者,其实现类有多种,比如普通线程池,定时调度线程池ScheduledExecutorService等,我们能把一个
Runnable,Callable提交到池中让其调度。
Future:是与Runnable,Callable进行交互的接口,比如一个线程执行结束后取返回的结果等等,还提供了cancel终止线程。
BlockingQueue:阻塞队列。
java.util.concurrent下主要的接口和类:
Executor:具体Runnable任务的执行者。
ExecutorService:一个线程池管理者,其实现类有多种,比如普通线程池,定时调度线程池ScheduledExecutorService等,我们能把一个
Runnable,Callable提交到池中让其调度。
Future:是与Runnable,Callable进行交互的接口,比如一个线程执行结束后取返回的结果等等,还提供了cancel终止线程。
BlockingQueue:阻塞队列。
对于多线程有了一点了解之后,那么来看看java.lang.concurrent包下面的一些东西。在此之前,我们运行一个线程都是显式调用了Thread的start()方法。我们用concurrent下面的类来实现一下线程的运行,而且这将成为以后常用的方法或者实现思路。
1、ExecutorService:
是一个接口,继承了Executor:
public interface ExecutorService extends Executor { }
2、Executor:
而Executor亦是一个接口,该接口只包含了一个方法:
void execute(Runnable command);
3、Executors:
该类是一个辅助类,此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。
此类支持以下各种方法:
• 创建并返回设置有常用配置字符串的 ExecutorService 的方法。
• 创建并返回设置有常用配置字符串的 ScheduledExecutorService 的方法。
• 创建并返回“包装的”ExecutorService 方法,它通过使特定于实现的方法不可访问来禁用重新配置。
• 创建并返回 ThreadFactory 的方法,它可将新创建的线程设置为已知的状态。
• 创建并返回非闭包形式的 Callable 的方法,这样可将其用于需要 Callable 的执行方法中。
• 创建并返回设置有常用配置字符串的 ScheduledExecutorService 的方法。
• 创建并返回“包装的”ExecutorService 方法,它通过使特定于实现的方法不可访问来禁用重新配置。
• 创建并返回 ThreadFactory 的方法,它可将新创建的线程设置为已知的状态。
• 创建并返回非闭包形式的 Callable 的方法,这样可将其用于需要 Callable 的执行方法中。
4、创建ExecutorService的方法:
newFixedThreadPool()
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
5、ExecutorService的方法:
shutdown
void shutdown()
SecurityException
- 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持 RuntimePermission
("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
awaitTermination
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
timeout
- 最长等待时间unit
- timeout 参数的时间单位InterruptedException
- 如果等待时发生中断请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。既是等待所有子线程执行结束。
execute
void execute(Runnable command)
command
- 可运行的任务RejectedExecutionException
- 如果不能接受执行此任务。NullPointerException
- 如果命令为 null在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
submit
Future<?> submit(Runnable task)
task
- 要提交的任务RejectedExecutionException
- 如果任务无法安排执行NullPointerException
- 如果该任务为 null提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功 完成时将会返回 null。
6、下面是相关的使用例子:
public class ExecutorServiceTest { public static void main(String[] args) throws IOException, InterruptedException { // 创建一个固定大小的线程池 ExecutorService service = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { System.out.println("创建线程" + i); Runnable run = new Runnable() { @Override public void run() { System.out.println("启动线程"); } }; // 在未来某个时间执行给定的命令 service.execute(run); } // 关闭启动线程 service.shutdown(); // 等待子线程结束,再继续执行下面的代码 service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); System.out.println("all thread complete"); } }
可以发现线程被循环创建,但是启动线程却不是连续的,而是由ExecutorService决定的。
相关推荐
- `newFixedThreadPool(int nThreads)`:创建固定大小的线程池,线程数量始终保持不变,超出的任务进入队列等待。 - `newSingleThreadExecutor()`:创建单线程的线程池,所有任务在线程池中串行执行。 示例: `...
- **newFixedThreadPool**:创建固定长度的线程池,可控制线程最大并发数,超出的线程会在队列中等待。 ```java ExecutorService executorService = Executors.newFixedThreadPool(3); ``` - **...
- `newFixedThreadPool(int nThreads)`:创建一个固定大小的线程池,线程数量固定,多余的提交任务会被放入任务队列等待。 - `newCachedThreadPool()`:创建一个可缓存线程池,会尽可能重用已存在的线程,如果所有...
在示例中,使用`Executors.newFixedThreadPool(int nThreads)`创建了一个固定大小的线程池,参数`nThreads`定义了线程池中允许的最大线程数。在这个例子中,线程池大小被设置为5,这意味着最多可以同时运行5个线程,...
常用的线程池有固定大小线程池、单线程线程池等。例如,我们可以创建一个固定大小的线程池,用于执行图像加载任务: ```java ExecutorService executorService = Executors.newFixedThreadPool(3); // 创建包含3个...
1. **固定大小线程池** (`Executors.newFixedThreadPool(int nThreads)`): 这种线程池的核心线程数和最大线程数相同,均为`nThreads`。当线程池满时,新提交的任务会在队列中等待,直到有线程空闲出来。适合处理...
- **newFixedThreadPool**:创建固定大小的线程池。适用于需要保持固定数量的线程处理任务的场景。 - **newCachedThreadPool**:创建一个可根据需要创建新线程的线程池。适用于处理大量短暂的异步任务,线程池会根据...
// 创建固定大小线程池 executor.execute(() -> { // 线程执行逻辑 }); executor.shutdown(); // 关闭线程池 ``` 5. 使用Executors的工厂方法 `Executors`类提供了一些静态工厂方法,如`newSingleThreadExecutor`...
2. 定长线程池:定长线程池是Java中的另一个常用的线程池,它的大小是固定的,可以指定线程池的大小。 ```java ExecutorService service = Executors.newFixedThreadPool(2); ``` 3. 单线程线程池:单线程线程池是...
1. **FixedThreadPool**:创建固定大小的线程池,可以复用指定数量的线程,减少了创建和销毁线程的开销。适合处理大量短小的任务。 ```java ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);...
- `newFixedThreadPool`:固定大小的线程池,适合执行大量重复性任务。 - `newSingleThreadExecutor`:只有一个线程的线程池,确保任务按顺序执行。 - `newCachedThreadPool`:可缓存的线程池,会根据需要创建新...
1. `newFixedThreadPool(int nThreads)`:创建一个固定大小的线程池,线程池的大小由传入的`nThreads`参数决定。一旦创建,线程池中的线程数量保持不变,即使有些线程空闲,也不会额外创建新的线程。当所有工作线程...
// 创建固定大小的线程池 executor.execute(new Runnable() { /* 实现run方法 */ }); ``` `ThreadPoolExecutor`允许更精细的配置,包括核心线程数、最大线程数、线程存活时间、工作队列类型等。例如: ```java ...
`newFixedThreadPool`是`java.util.concurrent`包中的一个线程池工厂方法,用于创建固定数量线程的线程池。`FutureTask`则是表示异步计算的结果,它实现了`RunnableFuture`接口,提供了对任务状态的查询和结果获取。...
3. **定长线程池**:`Executors.newFixedThreadPool(int nThreads)` 创建的线程池有固定数量的工作线程,不会因为任务量增加而动态扩展,适合处理固定数量的并发任务。 4. **定时线程池**:`...
1. 创建线程池:使用`Executors`静态工厂方法创建一个固定大小的线程池,如`ExecutorService executor = Executors.newFixedThreadPool(poolSize);` 2. 实现图片下载接口:定义一个接口,包含下载图片的方法,如`...
2. **固定大小线程池**(`newFixedThreadPool`):适用于固定数量的长期任务,线程数量固定,超出的任务会被放入队列等待执行。 3. **单线程执行器**(`newSingleThreadExecutor`):所有任务按顺序在一个单独的线程...
在这个例子中,我们使用 Executors.newFixedThreadPool 创建了一个固定大小的线程池,它会维护指定数量的线程来执行任务。这有助于避免频繁创建和销毁线程的开销,提高性能。 4. **Runnable 接口**:SquareTask 类...
通过`Executors`类提供的静态工厂方法,我们可以创建不同类型的线程池,如单线程池、固定大小线程池、缓存线程池等。线程池不仅可以重用已存在的线程,避免频繁创建和销毁线程的开销,还可以限制并发执行的任务数量...