1. 启动线程的最基本方式
在Java中用Runnable表示一个任务,需要在Runnable接口的run方法中实现任务的具体业务逻辑,然后创建一个Thread并调用start方法启动任务。
例如执行一个匿名任务:
new Thread(new Runnable() { public void run() { //.... } } ).start();
2. 使用Executor框架执行线程
Java中执行任务更灵活的方式是使用Executor框架。
java.util.concurrent.Executor是一个十分简单的接口,只有一个方法execute,参数为Runnable对象,表示对任务处理器的抽象。
public interface Executor { public abstract void execute(Runnable task); }
Executor还有一个更常用的接口是java.util.concurrent.ExecutorService,ExecutorService扩展了Executor接口的功能,添加了开启关闭任务处理器等功能。java.util.concurrent.Executors类是一个工具类,主要提供了很多创建Executor对象以及ExecutorService对象的工厂方法。
Executor框架实现了将任务的提交与任务的执行解耦,Executor框架基于生产者—消费者模式,任务的提交程序相当于生产者,而执行任务的线程相当于消费者。
假设我们要实现一个服务器程序,该服务器程序通过80端口接收请求,然后处理请求:
class MyServer { private class HandleRequestTask implements Runnable { HandleRequestTask(Socket client) { //..... } public void run() { //..... } }
public static void main(String[] args) { ServerSocket server = new ServerSocket(80); Socket client = null; while(true) { client = server.accept(); new Thread(new HandleRequestTask(client)).start(); } } }
在上述服务器中,我们每收到一个请求,就开启一个线程来处理该请求。上述代码中,任务的提交和执行是紧耦合的,而使用Executor接口就可以改进为如下程序:
public class MyServer { private static final Executor executor = Executors.newCachedThreadPool(); private class HandleRequestTask implements Runnable { HandleRequestTask(Socket client) { //..... } public void run() { //..... } } public static void main(String[] args) { ServerSocket server = new ServerSocket(80); Socket client = null; while(true) { client = server.accept(); executor.execute(new HandleRequestTask(client)); } } }
上述例子使用Executors类的newCachedThreadPool方法创建了一个线程池,该线程池也是对于每个请求采用一个线程来处理,实现的功能和第一个服务器程序一样,但比第一个服务器程序要灵活得多。我们可以使用不同的ExecutorService对象来执行不同的任务提交策略,例如使用newFixedThreadPool方法创建一个包含固定线程数目的线程池,使用固定数目的线程来处理客户端请求。
3. Callable与Future
Runnable接口表示任务执行的一个抽象,其中只有一个run方法,并且没有返回值,也不抛出任何异常,这样我们就无法了解任务执行是失败了还是成功了,也无法了解任务执行的进度。
对于需要返回任务执行结果的情况,Callable接口是一个更好的选择。java.util.concurrent.Callable<V>是一个泛型接口类,只有一个call方法,如果任务执行成功,则返回结果(类型为V),否则抛出一个异常。
public interface Callabel<V> { public abstract V call(); }
在Executors工具类中还提供了一些static的方法用于将Runnable对象转换成Callable对象。
java.util.concurrent.Future<V>接口用于表示一个任务执行的生命周期,任务的执行状态包括等待执行、正在执行和执行完成三种状态。Future提供了检查任务执行是否完成,以及获得执行结果的方法。
public interface Future<V> { public abstract boolean cancel(boolean mayInterruptIfRunning); public abstract V get(); public abstract V get(long timeout,TimeUnit unit); public abstract boolean isCancelled(); public abstract boolean isDone(); }
get方法用于获取任务的执行结果,如果任务已经完成则立即返回结果(执行成功)或者抛出异常ExecutionException(执行失败,任务被取消会抛出CancellationException),如果任务尚未完成,则该方法将阻塞至任务完成;cancel方法试图取消任务的执行;isCancelled方法用于判断任务是否在执行之前被取消;isDone方法用于判断任务是否已经处于执行完成状态(包括执行成功和执行失败)。
java.util.concurrent.FutureTask类是Future接口的实现类,实现了Future接口中的各个方法。
原文:http://www.cnblogs.com/jqctop1/p/4923261.html