Java深入学习28:Runnable和Callable
创建线程的四种方式(前两种没有返回值,后两种有)
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口通过FutureTask包装器来创建Thread线程
- 使用ExecutorService、Callable、Future实现有返回结果的多线程
Runnable和Callable的区别
- Runnable执行方法是run(),Callable是call()
- 实现Runnable接口的任务线程无返回值;实现Callable接口的任务线程能返回执行结果
- call方法可以抛出异常,run方法若有异常只能在内部消化
注意
- Callable接口支持返回执行结果,需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞!
- 如果线程出现异常,Future.get()会抛出throws InterruptedException或者ExecutionException;如果线程已经取消,会爬出CancellationException
示例
实现Runnable接口
public class RunnableDemo { public static void main(String[] args) { //2-实例化一个线程target MyRunnable mr = new MyRunnable(); for(int j=0; j<5; j++){ //3-实例化一个线程类,并传入线程target Thread mt = new Thread(mr); //4-调用线程类的start方法 mt.start(); } } } class MyRunnable implements Runnable{ private int num = (int)(Math.random()*100); //1-实现Runnable接口,并重写run方法 @Override public void run() { System.out.println(Thread.currentThread().getName() + " is working; num = " + num); } }
实现Callable接口
public class CallableDemo { public static void main(String[] args) { //2-创建Callable实现类 MyCallable mc = new MyCallable(); for(int j=0; j<10; j++){ //3-创建FutureTask。FutureTask实现了RunnableFuture接口,RunnableFuture接口继承了Runnable,Future两个接口,其中RunnableFuture接口继承了Runnable接口定义了 FutureTask ft = new FutureTask(mc); //3-创建线程 Thread t = new Thread(ft); //4-执行线程的start方法 t.start(); while(!ft.isDone()){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前线程正在执行执行---------"); } try { System.out.println("线程返回值: " + ft.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } } class MyCallable implements Callable { private int num = (int)(Math.random()*100); //1-实现Callable接口,并从重写call方法 @Override public Object call() throws Exception { System.out.println(Thread.currentThread().getName() + " is working; num = " + num); return (int)(Math.random()*100); } }
END