http://lavasoft.blog.51cto.com/62575/115112/
Java5之后,并发线程发生了根本性的变化,最重要的是很多新的启动、调度和管理线程的API。Java5之后,通过Executor启动线程比使用Threadstart()更好。在新特性中,可以轻松控制线程的启动、执行和关闭过程,也可以轻松使用线程池的特性。
一、创建任务
任务是实现Runnable接口的类别。
创建时,实run方法就可以了。
二、执行任务
通过java.util.concurrent.ExecutorService接口对象执行任务,该接口对象通过工具java.util.concurrent.创建Executors的静态方法。
本包定义的Executors Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类工厂及实用方法。
ExecutorService提供了管理终止的方法,并可以生成跟踪一个或多个异步任务的执行状态 Future 的方法。 可以关闭 ExecutorService,这将导致它停止接受新任务。关闭后,执行程序最终将终止。此时,没有任务在执行,没有任务在等待执行,新任务无法提交。
executorService.execute(new TestRunnable());
1、创建Executorservicer
通过工具类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、将任务添加到线程执行中
当将任务添加到线程池中时,线程池将为每个任务创建一个线程,并在以后的某个时间自动执行。
三、关闭执行服务对象
executorService.shutdown();
四、综合实例
package concurrent; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by IntelliJ IDEA. * * @author leizhimin 2008-11-25 14:28:59 */ public class TestCachedThreadPool { public static void main(String[] args) { // ExecutorService executorService = Executors.newCachedThreadPool(); ExecutorService executorService = Executors.newFixedThreadPool(5); // ExecutorService executorService = Executors.newSingleThreadExecutor(); for ( int i = 0; i < 5; i++) { executorService.execute( new TestRunnable()); System.out.println( "************* a" + i + " *************"); } executorService.shutdown(); } } class TestRunnable implements Runnable { public void run() { System.out.println(Thread.currentThread().getName() + “调用线程。"); while ( true) { try { Thread.sleep(5000); System.out.println(Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
运行结果:
************* a0 ************* ************* a1 ************* pool-1-thread-调用2线程。 ************* a2 ************* pool-1-thread-调用3线程。 pool-1-thread-调用1线程。 ************* a3 ************* ************* a4 ************* pool-1-thread-调用4线程。 pool-1-thread-调用5线程。 pool-1-thread-2 pool-1-thread-1 pool-1-thread-3 pool-1-thread-5 pool-1-thread-4 pool-1-thread-2 pool-1-thread-1 pool-1-thread-3 pool-1-thread-5 pool-1-thread-4 ...
五、获取任务执行的返回值
Java5之后,任务分为两类:一类是实现Runnable接口的类,另一类是实现Callable接口的类。两者都可以由ExecutorService执行,但Runnable任务没有返回值,而Callable任务有返回值。而且Callable的call()方法只能通过ExecutorService进行 submit ( Callable <T>task)执行方法,并返回一个 <T> Future <T>,这意味着任务等待完成。 Future。
public interface Callable<V>
返回结果并可能抛出异常任务。实现者定义了一个没有任何参数的电话
CallableRunnable,两者都是为那些实例可能由另一个线程执行的类别设计的。但是Runnable
Executors包含一些从其他普通形式转变为 Callable
callable中的call()方法类似于runnable中的run()方法,即前者有返回值,后者没有。
当将Callable对象传递给Executorservice的submit方法时,call方法将自动在线程上执行,并将执行结果返回到future对象。
同样,如果将Runnable对象传递给Executorservice的Submit方法,Run方法将自动在线程上执行,并将执行结果返回Future对象,但在Future对象上调用get方法将返回null。
不幸的是,在Java 在API文档中,这个介绍非常混乱。估计是翻译还没搞清楚的原因。或者说注释不到位。以下是一个例子:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; /** * Calable接口测试 * * @author leizhimin 2008-11-26 9:20:13 */ public class CallableDemo { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); List<Future<String>> resultList = new ArrayList<Future<String>>(); //创建10个任务并执行 for ( int i = 0; i < 10; i++) { //使用ExecutorService执行Callable类型的任务,将结果保存在future变量中 Future<String> future = executorService.submit( new TaskWithResult(i)); ////将任务执行结果存储在List中 resultList.add(future); } ///遍历任务结果 for (Future<String> fs : resultList) { try { System.out.println(fs.get()); ////打印每个线程(任务)执行的结果 } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } finally { //启动顺序关闭,执行以前提交的任务,但不接受新任务。若已关闭,则调用无其他作用。 executorService.shutdown(); } } } } class TaskWithResult implements Callable<String> { private int id; public TaskWithResult( int id) { this.id = id; } /** * 任务的具体过程,一旦任务传递给ExecutorServicesubmit方法,该方法将在一个线程上自动执行。 * * @return * @throws Exception */ public String call() throws Exception { System.out.println( "call()方法自动调用,干活!!!! " + Thread.currentThread().getName()); ////模拟耗时的操作 for ( int i = 999999; i > 0; i--) ; return "call()方法自动调用,任务的结果是:“ + id + " " + Thread.currentThread().getName(); } }
运行结果:
call()方法自动调用,工作!!! pool-1-thread-1 call()方法自动调用,工作!!! pool-1-thread-3 call()方法自动调用,工作!!! pool-1-thread-4 call()方法自动调用,工作!!! pool-1-thread-6 call()方法自动调用,工作!!! pool-1-thread-2 call()方法自动调用,工作!!! pool-1-thread-5 call()方法自动调用,任务结果为:0 pool-1-thread-1 call()方法自动调用,任务结果如下:1 pool-1-thread-2 call()方法自动调用,干活!!!! pool-1-thread-2 call()方法自动调用,工作!!! pool-1-thread-6 call()方法自动调用,工作!!! pool-1-thread-4 call()方法自动调用,任务结果如下:2 pool-1-thread-3 call()方法自动调用,工作!!! pool-1-thread-3 call()方法自动调用,任务结果如下:3 pool-1-thread-4 call()方法自动调用,任务结果如下:4 pool-1-thread-5 call()方法自动调用,任务结果如下:5 pool-1-thread-6 call()方法自动调用,任务结果如下:6 pool-1-thread-2 call()方法自动调用,任务结果如下:7 pool-1-thread-6 call()方法自动调用,任务结果如下:8 pool-1-thread-4 call()方法自动调用,任务结果如下:9 pool-1-thread-3 Process finished with exit code 0