JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
A、public static ExecutorService newCachedThreadPool()
B、public static ExecutorService newFixedThreadPool(int nThreads)
C、public static ExecutorService newSingleThreadExecutor()
这些方法的返回值是ExecutorService对象
该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。
上一次实现的是执行Runnable对象的,这次实现下Callable对象的
注意:Callable:是带泛型的接口。这里指定的泛型其实是call()方法的返回值类型。
例子:多线程同时对不同的数段进行求和
首先创建一个类来继承Callable接口
1 public class MyCallable implements Callable<Integer> { 2 3 // 由于这里需要2个数,开始和结束的数值。 4 // 所以创建对象,并且写构造方法接收数值 5 private int start; 6 private int end; 7 8 public MyCallable(int start, int end) { 9 this.start = start; 10 this.end = end; 11 } 12 int sum = 0; 13 public Integer call() throws Exception { 14 for (int x = start; x <= end; x++) { 15 16 sum += x; 17 } 18 return sum; 19 } 20 21 }
再创建测试类:
1 public class CallableDemo { 2 3 public static void main(String[] args) throws InterruptedException, 4 ExecutionException { 5 6 // 创建线程池对象 7 ExecutorService pool = Executors.newFixedThreadPool(3); 8 9 // 调用方法 10 // Future<?> submit(Runnable task) 11 // <T> Future<T> submit(Callable<T> task) 12 // 这里需要使用泛型来接收结果,由于Callable中的泛型就是返回类型,所以是用Future<T> 13 Future<Integer> f1 = pool.submit(new MyCallable(1, 100)); 14 Future<Integer> f2 = pool.submit(new MyCallable(100, 200)); 15 Future<Integer> f3 = pool.submit(new MyCallable(1, 200)); 16 17 // 由于Mycallable类返回了计算的结果,所以这里需要一个方法来接收这个结果 18 // V get(); 这里需要抛异常 19 Integer n1 = f1.get(); 20 Integer n2 = f2.get(); 21 Integer n3 = f3.get(); 22 23 System.out.println(n1); 24 System.out.println(n2); 25 System.out.println(n3); 26 27 //关闭线程 28 pool.shutdown(); 29 30 } 31 }
这种方式的好处是:
A、可以有返回值
B、可以抛出异常
弊端是:
A、代码比较复杂,所以一般不用