一、说明
Java 提供了三种创建线程的方法
- 实现
Runnable
接口
- 继承
Thread
类本身
- 通过
Callable
和Future
创建线程
Callable和Future的引入
- 继承
Thread
或实现Runnable
接口,任务执行完成后无法获取执行结果
- 而要获取执行结果,必须通过共享变量或者使用线程通信的方式来达到效果
- Java 1.5 开始引入了
Callable
和Future
,执行任务完成后可获取执行结果,简单来说就是一个产生结果,一个拿到结果
ExecutorService
ExecutorService
是Java中对线程池定义的一个接口,继承Executor
接口,用于管理线程对象,可以使用Executors
工厂类来创建ExecutorService
的实例(即线程池)
ExecutorService executorService1 = Executors.newSingleThreadExecutor(); ExecutorService executorService2 = Executors.newFixedThreadPool(10); ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
ExcutorService
提供的三种方法都有相应的结果返回
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task);
- 同时
Executors
类提供方法能把Runnable
对象包装成Callable
对象
public static Callable<Object> callable(Runnable task) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<Object>(task, null); }
public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<T>(task, result); }
二、理解
Callable
java.lang
包下Runnable
接口.run()
方法返回类型为void
public interface Runnable { public abstract void run(); }
java.util.concurrent
包下Callable
接口,.call()
方法返回的类型为传递进来的V - Value
(值)类型
public interface Callable<V> { V call() throws Exception; }
实现方法
Runnable
或Callable
实现类使用ExecutorSevice
接口的.submit()
方法提交,不使用没有返回值的.execute()
方法
Future
java.util.concurrent
包下Future<V>
接口,对Runnable
或Callable
对象执行任务完成后获取执行结果
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
mayInterruptRunning
表示是否中断执行中的线程
boolean cancel()
尝试取消任务的执行,如果任务已经完成或已被取消,则返回false;如果任务已经启动,将以中断执行线程的方式停止该任务,停止成功则返回true
boolean isDone()
若任务完成,则返回true
boolean isCancelled()
若任务在完成前取消,则返回true
get()
获取执行结果,必须等待任务完成后才返回结果
get(long timeout, TimeUnit unit)
获取执行结果,timeout表示等待的最长时间,unit表示时间单位,在指定时间内还没获取到结果,则返回null
三、实现
1.实现接口
创建CallableThreadDemo
类实现Callable
接口
public class CallableThreadDemo implements Callable{ @Override public String call() throws Exception { System.out.println("Callable子线程: " +Thread.currentThread().getName()+ " 开启"); return "我是Callable子线程: " +Thread.currentThread().getName()+ " 产生的结果"; } }
2.执行线程
创建CallableTest
类执行测试,将创建好的线程对象通过.submit()
方法提交到线程池去执行,线程执行后,返回值Future
可被拿到
public class CallableTest { public static void main(String[] args) { // 1.创建线程池 ExecutorService executorService = Executors.newSingleThreadExecutor(); // 2.创建Callable子线程对象任务 CallableThreadDemo callableThread_1 = new CallableThreadDemo(); // 3.提交任务到线程池 Future future = executorService.submit(callableThread_1); // 4.获取执行结果 try { System.out.println("主线程开始执行"); System.out.println("主线程要取得Callable子线程的结果"); if (future.get()!=null){ //输出获取的结果 System.out.println(future.get()); }else { //输出未获取到结果 System.out.println("future.get()未获取到结果"); } } catch (InterruptedException e){ e.printStackTrace(); }catch (Exception e) { e.printStackTrace(); } // 5.关闭线程池 executorService.shutdown(); System.out.println("主线程执行完成"); } }