Java深入学习28:Runnable和Callable

Java深入学习28:Runnable和Callable

 创建线程的四种方式(前两种没有返回值,后两种有)

  1. 继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口通过FutureTask包装器来创建Thread线程
  4. 使用ExecutorService、Callable、Future实现有返回结果的多线程

Runnable和Callable的区别

  1. Runnable执行方法是run(),Callable是call()
  2. 实现Runnable接口的任务线程无返回值;实现Callable接口的任务线程能返回执行结果
  3. call方法可以抛出异常,run方法若有异常只能在内部消化

注意

  1. Callable接口支持返回执行结果,需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞!
  2. 如果线程出现异常,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