Java多线程详解(二)--Runnable和Callable

Java多线程实现方式主要有四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。
其中前两种方式线程执行完后都没有返回值,后两种是带返回值的。

Runnable和Callable的区别

Runnable接口

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

Callable接口

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Runnable和Callable的区别

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

注意
Callable接口支持返回执行结果,需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取结果;当不调用此方法时,主线程不会阻塞!
如果线程出现异常,Future.get()会抛出throws InterruptedException或者ExecutionException;如果线程已经取消,会爬出CancellationException

Callable示例

package com.keda.activiti.config;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @program: xxx
 * @description:
 * @author: shuonar
 * @create: 2020-06-02 16:52
 **/
public class ExecutorsTest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(3000);
                System.out.println("Thread_current="+Thread.currentThread());

                return "Hello World!";
            }
        };

        System.out.println("start thread ....");
        Future<String> future =  executorService.submit(callable);
        try {
            System.out.println("future.get()=" + future.get());
        }catch (Exception e){
            e.printStackTrace();
        }

        System.out.println("end thread...");
        // 切记:关闭线程池
        executorService.shutdown();
    }
}

start thread ....
Thread_current=Thread[pool-1-thread-1,5,main]
future.get()=Hello World!
end thread...

其它

在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
1.避免点继承的局限,一个类可以实现多个接口
2.资源共享

Runnable接口和Thread之间的联系

public class Thread extends Object implements Runnable

由此可见:Thread类也是Runnable接口的子类

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。