Java多线程——3 任务的提交者和执行者Executor

Java SE5引入Executor框架将为你管理Thread对象,从而简化了并发编程。Executor框架是指j一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。而Executor在客户端和执行任务之间提供了一个间接层,Executor代替客户端执行任务。Executor允许你管理异步任务的执行,而无须显式地管理线程的生命周期。

Java多线程——3 任务的提交者和执行者Executor_第1张图片


Executors类,提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口。

Executor才是任务的执行者和提交者,有两种类型的任务:Runnable、 Callable,其中Callable是需要返回值的任务

Future代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则get()会使当前线程阻塞。FutureTask实现了Future和Runable。Callable代表一个有返回值得操作。

CompletionService用于执行多个任务,将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果。


写个Executor框架的小例子

public class ExecutorServiceTest
	{

		public static void main(String[] args) throws InterruptedException,
				ExecutionException
		{
			ExecutorService es = Executors.newFixedThreadPool(10);

			for (int i = 0; i < 10; i++)
			{
				MyCallable callable = new MyCallable(i);
				FutureTask ft = new FutureTask(callable);
				es.submit(ft);
				System.out.println(ft.get());
			}

		}

	}

class MyCallable implements Callable
	{
		int i;

		public MyCallable(int i)
		{
			this.i = i;

		}

		@SuppressWarnings("static-access")
		@Override
		public String call() throws Exception
		{
			Thread.sleep((long) (Math.random() * 1000));
			return "Callable " + i;
		}

	}

CompletionService

它与ExecutorService最主要的区别在于submit的task不一定是按照加入时的顺序完成的。CompletionService对ExecutorService进行了包装,内部维护一个保存Future对象的BlockingQueue。只有当这个Future对象状态是结束的时候,才会加入到这个Queue中,take()方法其实就是Producer-Consumer中的Consumer。它会从Queue中取出Future对象,如果Queue是空的,就会阻塞在那里,直到有完成的Future对象加入到Queue中。

//这个东西的使用上很类似于CallableFutureTest,不同的是,它会首先取完成任务的线程。
public class CompletionServiceTest
	{
		
		public static void main(String[] args) throws InterruptedException,
				ExecutionException
		{
			ExecutorService exec = Executors.newFixedThreadPool(10);
			// 创建CompletionService
			CompletionService serv = new ExecutorCompletionService(exec);
			
			for (int index = 0; index < 5; index++)
			{
				final int NO = index;
				// Callable 接口类似于 Runnable
				Callable downImg = new Callable()
				{
					public String call() throws Exception
					{
						Thread.sleep((long) (Math.random() * 10000));
						return "Downloaded Image " + NO;
					}
				};
				// 提交要执行的值返回任务,并返回表示挂起的任务结果的 Future。在完成时,可能会提取或轮询此任务。
				serv.submit(downImg);
			}
			Thread.sleep(1000 * 2);
			System.out.println("Show web content");
			for (int index = 0; index < 5; index++)
			{
				// 获取并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。
				Future task = serv.take();
				// 如有必要,等待计算完成,然后获取其结果。
				String img = task.get();
				System.out.println(img);
			}
			System.out.println("End");
			// 关闭线程池
			exec.shutdown();
		}
	}




你可能感兴趣的:(Java,Java并发编程)