转:线程池ExecutorService的submit和execute
在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动、调度、管理线程的一大堆API了。在Java5以后,通过 Executor来启动线程比用Thread的start()更好。在新特征中,可以很容易控制线程的启动、执行和关闭过程,还可以很容易使用线程池的特 性。
一、创建任务
任务就是一个实现了Runnable接口的类。
创建的时候实run方法即可。
二、执行任务
通过java.util.concurrent.ExecutorService接口对象来执行任务,该接口对象通过工具类java.util.concurrent.Executors的静态方法来创建。
Executors此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。
ExecutorService提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以关闭 ExecutorService,这将导致其停止接受新任务。关闭后,执行程序将最后终止,这时没有任务在执行,也没有任务在等待执行,并且无法提交新任 务。
executorService.execute(new TestRunnable());
1、创建ExecutorService
通过工具类java.util.concurrent.Executors的静态方法来创建。
Executors此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。
比如,创建一个ExecutorService的实例,ExecutorService实际上是一个线程池的管理工具:
ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorService executorService = Executors.newFixedThreadPool(3);
ExecutorService executorService = Executors.newSingleThreadExecutor();
2、将任务添加到线程去执行
当将一个任务添加到线程池中的时候,线程池会为每个任务创建一个线程,该线程会在之后的某个时刻自动执行。
示例1:
@Test
publicvoid testDemo() throws Exception {
//单例线程,任意时间(同一时间)池中只能有一个线程
ExecutorService es = Executors.newSingleThreadExecutor();
es.execute(new Runnable() {
@Override
publicvoid run() {
System.err.println("线程启动并运行"+Thread.currentThread().getName());
}
});
es.execute(new Runnable() {
@Override
publicvoid run() {
System.err.println("第二个也运行了"+Thread.currentThread().getName());
}
});
//Thread.sleep(1000 * 60 * 60);
}
运行结果如下:两个都会执行,但程序只会使用一个线程来运行。
线程启动并运行pool-1-thread-1
第二个也运行了pool-1-thread-1
示例2:
@Test
publicvoid testDemo3() throws Exception {
//声明一个线程池
ExecutorService ex = Executors.newCachedThreadPool();
for (int i = 0; i < 4; i++) {
finalint a = i;
//每一次execute方法,都是向池中放入一个对象
ex.execute(new Runnable() {
publicvoid run() {
while(true){
System.err.println("测试...."+a+">"
+Thread.currentThread().getName()+","
+Thread.currentThread().isDaemon());
try{
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}
}
}
});
}
Thread.sleep(1000*60*60);
}
输出的结果如下:从中可以发现,第四个一组输出,即一共创建了四个线程,每次每个线程都会执行输出,但不按顺序:位每一次输出都四个算是一组
测试....0>pool-1-thread-1,false
测试....3>pool-1-thread-4,false
测试....2>pool-1-thread-3,false
测试....1>pool-1-thread-2,false
测试....0>pool-1-thread-1,false
测试....3>pool-1-thread-4,false
测试....2>pool-1-thread-3,false
测试....1>pool-1-thread-2,false
测试....1>pool-1-thread-2,false
测试....2>pool-1-thread-3,false
测试....3>pool-1-thread-4,false
测试....0>pool-1-thread-1,false
示例3:
publicvoid testCall() throws Exception{
//声明一个类,可以被调用,类似于线程,但它可以拥有返回值
class MyCall implements Callable<String>{
privateintseq;
public MyCall(int seq){
this.seq=seq;
}
//抛出异常并可以拥有返回值
public String call() throws Exception {
System.err.println("执行"+seq+","+Thread.currentThread().getName());
Thread.sleep(3000);
System.err.println("Weak up "+seq);
return"完成"+seq;//这是返回值
}
}
ExecutorService es = Executors.newCachedThreadPool();//创建线程池对象
List<Future<String>> result =new ArrayList<Future<String>>();//放结果用的集合
for(int i=0;i<3;i++){
Future<String> f=es.submit(new MyCall(i));//线程执行完成以后可以通过引用获取返回值
result.add(f);
}
for(Future<String> f:result){
System.err.println("返回值:"+f.get());//输出返回的值
}
System.err.println("完成....");
}
相关推荐
### 线程池的submit和execute方法的区别详解 #### 一、引言 线程池作为Java并发编程中的一项关键技术,在实现高效并发任务管理方面发挥着重要作用。而在实际开发中,开发者经常会遇到两种用于向线程池提交任务的...
`ExecutorService`通过`execute()`和`submit()`这两个方法来提交任务进行执行。理解并熟练运用这两个方法对于优化并发性能至关重要。 `execute()`方法: `execute(Runnable command)`是`ExecutorService`最基础的...
Java线程池ExecutorService是Java并发编程中非常重要的一个组件,它通过管理和复用线程资源,有效地控制并发任务的执行,从而提高系统的性能和稳定性。本文将详细讲解ExecutorService的原理、使用场景以及如何通过...
在 Executor 接口中,只定义了 execute 方法,而 submit 方法则是在 ExecutorService 接口中定义的。 ```java public interface ExecutorService extends Executor { ... <T> Future<T> submit(Callable<T> task)...
例如,对于`ExecutorService es`,执行`submit()`方法时,内部会将`Runnable`或`Callable`包装成`RunnableFuture`实例,如`FutureTask`。`ExecutorService`执行这个`RunnableFuture`,任务完成后,结果可通过`Future...
2. **提交任务**:使用`execute(Runnable task)`方法提交Runnable任务,或者使用`submit(Callable<T> task)`提交Callable任务并获取Future结果。 3. **关闭线程池**:任务执行完毕后,应调用`shutdown()`或`shutdown...
2. **ExecutorService接口**:继承自Executor接口,增加了管理和控制线程池的功能,如`submit()`用于提交任务,`shutdown()`用于关闭线程池,`shutdownNow()`用于尝试停止所有正在执行的任务等。 3. **...
通常,我们不会直接使用`Executor`,而是使用它的子接口`ExecutorService`,因为`ExecutorService`提供了更多的功能,如任务的提交、管理和关闭线程池。 2. **Executors** `Executors`是`java.util.concurrent`包...
通常,我们会创建一个线程池,然后使用`submit()` 或 `execute()` 方法来提交任务。测试代码可能会包含以下部分: ```java ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个固定大小的...
2. 使用 `ExecutorService.execute()` 或 `submit()` 方法提交任务到线程池。 3. 当不再有新任务提交时,调用 `shutdown()` 方法通知线程池停止接收新任务,已提交的任务会继续执行。 4. 要强制停止所有任务,可以...
此外,线程池还可以通过`execute()`方法提交Runnable任务,或通过`submit()`方法提交Callable任务,并返回Future对象,以便于获取任务执行结果。 在实际应用中,我们还可以使用`Executors`类提供的静态工厂方法快速...
通过`ExecutorService`的`execute(Runnable task)`方法提交任务,或者使用`submit(Callable<T> task)`提交返回结果的任务。`Runnable`接口用于无返回值的任务,而`Callable`接口则支持带返回值的任务。 5. **关闭...
5. **线程池的提交任务方式**:使用`execute()`方法提交Runnable任务,或使用`submit()`方法提交Callable任务。 6. **关闭线程池**:使用`shutdown()`或`shutdownNow()`方法优雅地关闭线程池,确保所有已提交的任务...
JDK线程池是Java中的一个内置线程池实现,它提供了一个ExecutorService接口,该接口提供了execute、submit、shutdown等方法来管理线程池。JDK线程池可以通过ThreadPoolExecutor类来创建,ThreadPoolExecutor类提供了...
线程池通常使用`execute()`方法来提交`Runnable`任务,或者使用`submit()`方法来提交`Callable`任务,后者会返回一个`Future`对象,可以用来获取任务执行的结果或检查任务状态。 线程池的工作流程大致如下: 1. **...
线程池中重要的方法包括execute()、submit()、shutdown()、shutdownNow()、isTerminated()和isShutdown()等。execute()方法用于执行Runnable任务;submit()方法可以用来提交Callable或Runnable任务,并返回一个...
Java并发编程中的Executor、Executors和ExecutorService是Java并发编程框架的重要组成部分,它们为开发者提供了高效管理和控制线程执行的工具。以下是对这些概念的详细解释: 1. Executor: Executor是一个接口,它...
- `submit(Runnable task)`:和`execute()`类似,但submit()方法返回一个Future对象,可以通过这个对象获取任务的执行结果。 - `shutdown()`:关闭线程池,不再接受新任务,但会等待正在执行的任务完成。 - `...
根据`execute()`或`submit()`方法的使用,任务可能返回结果或不返回结果。 在实际应用中,线程池大小的配置是非常关键的,过大可能导致内存消耗过多,过小则可能导致CPU资源未被充分利用。线程池通过`...