如果你开发项目的时候用到很多的short-lived任务,这里推荐使用“线程池”这项技术。你可以创建一个线程池来执行池中的的任务,来取代每次执行任务是都要为新的任务来new和discard。如果一个线程在池中是可用状态,那么任务将立即执行。执行完成之后线程返回池中,否则,任务将一直等待直到有线程处在可用状态。
J2SE 5.0为大家提供了一个新的java.util.concurrent package,并且在这个报中提供了一个pre-built 的线程池架构。在java.util.concurrent中提供了一个Executor 接口,里面有一个execute的方法,参数是Runnable 类型
public interface Executor {
public void execute(Runnable command);
}
使用线程池架构,你就必须创建一个Executor实例,然后你给他分配一些runnable任务,例如:
Executor executor = ...;
executor.execute(aRunnable1);
executor.execute(aRunnable2);
然后你创建或者找到Executor的实现类,实现类可以立即(或者连续)执行分配的任务,例如:
class MyExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}
concurrency utilities也包括了一个ThreadPoolExecutor类,它提供了很多对线程的一般性操作,提供了四个构造函数,每个都可以指定如:线程池大小,持续时间,一个线程factory,和拒绝线程的handler。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
但是你不必声明构造函数,Executors类会为你创建一个线程池。在一种最简单的情况下,你在Executors类中声明了newFixedThreadPool方法,并且在池中分配了许多线程。你可以使用ExecutorService(继承Executor的一个接口),去execute和submit 那些Runnable任务,使用ExecutorService中的submit方法可以得到一个返回结果,当然submit也可以返回一个Future对象用来检查任务是否执行。
让我们来先做一个Runnable类,名字为NamePrinter,它通知你运行、暂停、和耗费的时间。
public class NamePrinter implements Runnable {
private final String name;
private final int delay;
public NamePrinter(String name, int delay) {
this.name = name;
this.delay = delay;
}
public void run() {
System.out.println("Starting: " + name);
try {
Thread.sleep(delay);
} catch (InterruptedException ignored) {
}
System.out.println("Done with: " + name);
}
}
然后下面是我们测试的项目UsePool,它创建一个有三个线程的线程池,分配了10个任务给它(运行10次NamePrinter),UsePool在被shutdown 和 awaitTermination之前将等待并执行分配的任务。一个ExecutorService必须要在terminated之前执行shutdown,shutdownNow方法是立即尝试shutdown操作。shutdownNow 方法将返回没有被执行的任务。
import java.util.concurrent.*;
import java.util.Random;
public class UsePool {
public static void main(String args[]) {
Random random = new Random();
ExecutorService executor =
Executors.newFixedThreadPool(3);
// Sum up wait times to know when to shutdown
int waitTime = 500;
for (int i=0; i<10; i++) {
String name = "NamePrinter " + i;
int time = random.nextInt(1000);
waitTime += time;
Runnable runner = new NamePrinter(name, time);
System.out.println("Adding: " + name + " / " + time);
executor.execute(runner);
}
try {
Thread.sleep(waitTime);
executor.shutdown();
executor.awaitTermination
(waitTime, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {
}
System.exit(0);
}
}
输出的结果是:
Adding: NamePrinter 0 / 30
Adding: NamePrinter 1 / 727
Adding: NamePrinter 2 / 980
Starting: NamePrinter 0
Starting: NamePrinter 1
Starting: NamePrinter 2
Adding: NamePrinter 3 / 409
Adding: NamePrinter 4 / 49
Adding: NamePrinter 5 / 802
Adding: NamePrinter 6 / 211
Adding: NamePrinter 7 / 459
Adding: NamePrinter 8 / 994
Adding: NamePrinter 9 / 459
Done with: NamePrinter 0
Starting: NamePrinter 3
Done with: NamePrinter 3
Starting: NamePrinter 4
Done with: NamePrinter 4
Starting: NamePrinter 5
Done with: NamePrinter 1
Starting: NamePrinter 6
Done with: NamePrinter 6
Starting: NamePrinter 7
Done with: NamePrinter 2
Starting: NamePrinter 8
Done with: NamePrinter 5
Starting: NamePrinter 9
Done with: NamePrinter 7
Done with: NamePrinter 9
Done with: NamePrinter 8
注意前三个NamePrinter对象启动的非查的快,之后的NamePrinter对象每次启动都要等待前面的执行完成。
在J2SE 5.0有非常多的pooling framework可以用,例如,你可以创建一个scheduled线程池……
更多信息还是看官方的concurrency utilities,地址:http://java.sun.com/j2se/1.5.0/docs/guide/concurrency/
分享到:
相关推荐
1. 工作线程(Worker Threads):线程池中的线程,负责执行任务。 2. 任务队列(Task Queue):存储待执行任务的队列,当工作线程空闲时,会从队列中取出任务执行。 3. 拒绝策略(Rejection Policy):当任务队列满...
2. newFixedThreadPool(int nThreads):创建一个固定大小的线程池,池中维护着指定数量的工作线程,一旦工作线程因执行任务结束,将立即补充新的工作线程。 3. newCachedThreadPool():创建一个可缓存的线程池,...
在Django中,使用线程池的目的不仅仅是为了异步执行任务,还需要能够对这些异步任务进行有效的管理和监控。通过返回一个“期程”(future)对象,可以跟踪任务的执行状态,了解任务是否仍在执行中。此外,全局线程池...
带任务描述及执行时间的线程池执行框架, 使用Java 编写, 可以方便地完成多线程任务
1. **初始化线程执行任务**:如果当前工作线程数小于核心线程数,会立即创建新的线程执行任务。 2. **任务入队**:如果工作线程数达到或超过核心线程数,任务会被放入工作队列等待执行。这里使用`offer()`方法尝试...
线程池是一种资源管理策略,它预先创建一组线程,待有任务需要执行时,从池中取出一个线程来执行任务,完成后线程并不销毁,而是返回线程池等待下一次任务。这种机制避免了频繁地创建和销毁线程带来的开销,提高了...
**使用线程池执行任务** 创建好任务类后,我们可以将其添加到线程池并启动: ```cpp MyTask* task = new MyTask(); QThreadPool::globalInstance()->start(task); ``` **QTcpSocket用于网络通信** 在上述线程池...
任务线程池是一种高效利用系统资源、管理并发执行任务的机制。在多核或多处理器的系统中,线程池能够显著提升程序的性能和响应时间,避免了频繁创建和销毁线程带来的开销。线程池的核心思想是重用已存在的线程来执行...
通过设定线程池大小,可以限制并发执行的任务数量,避免资源过度消耗。 `FutureTask`是线程池处理任务的一种方式,它不仅包含了一个`Runnable`或`Callable`任务,还提供了检查任务是否完成、获取结果、取消任务等...
ExecutorService是线程池的基本服务接口,ThreadPoolExecutor是其具体实现,用于管理一组可重用的工作线程,而ScheduledThreadPoolExecutor则支持定时及周期性执行任务。 任务(Task)是在线程池中执行的工作单元,...
Spring Boot 使用自定义配置的线程池执行 Async 异步任务 在 Spring Boot 中执行异步任务时,默认情况下使用的是默认的线程池,但是,在实际项目中,我们可能需要根据项目的需求来定制自己的线程池。下面将介绍如何...
`_promain.cpp`是主程序文件,展示了如何使用线程池执行任务。它可能包括以下部分: 1. **`main`函数**:创建线程池实例,然后提交一系列任务。任务可以是函数对象(functors)、函数指针或Lambda表达式,只要它们...
1. **ThreadPool.QueueUserWorkItem**:这是C#中使用线程池执行异步任务的主要方法。调用此方法时,传入一个委托(Delegate),线程池会在适当的时候执行该委托代表的方法。 2. **WaitHandle** 和 **...
线程池是一种高效的并发编程方式,但是在使用线程池时,需要确保所有任务都已经执行完毕,以避免系统资源的浪费。 在本文中,我们将介绍如何使用 Java 判断线程池所有任务是否执行完毕的操作。首先,我们需要创建一...
在代码中,我们创建了一个线程池,然后执行一个打印任务,打印出当前java进程的总线程数。结果显示,在创建到15万个线程时,内存占用百分百后java应用崩溃。说明线程未被回收。 因此,使用完线程池后一定要关闭,...
线程池是一种多线程处理形式,预先创建了若干个线程,当有任务需要执行时,会从线程池中取出一个线程来执行任务,任务执行完毕后,线程返回线程池中等待新的任务。这种机制避免了频繁创建和销毁线程带来的性能开销,...
使用libstpool库,开发者首先需要初始化线程池,指定线程数量和任务队列的最大容量。然后,可以创建任务并将其加入到任务队列中,设定任务的优先级。当所有任务完成后,调用相应的函数关闭线程池。 1. 初始化线程池...
使用线程池执行任务: ```java executor.execute(new Runnable() { @Override public void run() { // 任务代码 } }); ``` 线程池的关闭: ```java executor.shutdown(); // 不接受新任务,但已提交的任务会...
- `Main` 类中创建了线程池对象,然后创建`MyThread`实例并提交给线程池执行。由于线程池大小为2,因此最多同时只有2个线程执行任务,其他任务会等待。 通过以上介绍,我们可以看到Java中的线程池是如何工作以及...
总结来说,这篇博文探讨了如何在Spring中使用线程池执行定时任务,包括配置线程池、创建定时任务、异常处理和线程安全。同时,提到了Spring MVC在Web开发中的角色,以及它如何与任务调度协同工作。理解和掌握这些...