Runable与Callable的区别

Runable与Callable的区别:
public interface Callable<V> {
    V call() throws Exception;//V是Callable返回值的类型
}
public interface Runnable {
    public abstract void run();
}
Runable与Callable相同点:
1、两者都是接口;
2、两者都可用来编写多线程程序;
3、两者都需要调用Thread.start()启动线程;
不同点:
1、实现Callable接口的任务线程能返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取call()返回的结果;当不调用此方法时,主线程不会阻塞;而实现Runnable接口的任务线程不能返回结果;
2、Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;
 
 
Callable的3种启动线程的方式
1、Thread启动
public class CallableImpl implements Callable<String> {
    private String acceptStr;
    public CallableImpl(String acceptStr) {
        this.acceptStr = acceptStr;
    }
    @Override
    public String call() throws Exception {
        // 任务等待1 秒
        Thread.sleep(1000);
        return this.acceptStr + ",hello!";
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //Callable<String> callable = new CallableImpl("afei");
        CallableImpl impl=new CallableImpl ("afei");
        FutureTask<String> task = new FutureTask<String>(impl);
        long beginTime = System.currentTimeMillis();
        // 创建线程
        new Thread(task).start();
        // 调用get()阻塞主线程,反之,线程不会阻塞
        String result = task.get();//阻塞主线程,直至1s后获取到call()的返回内容
        System.out.println("hello : " + result);//返回:afei,hello!
    }
}
2、ExecutorService 启动
public class CallableImpl implements Callable<String> {
    private String acceptStr;
    public CallableImpl(String acceptStr) {
        this.acceptStr = acceptStr;
    }
    @Override
    public String call() throws Exception {
        // 任务等待1 秒
        Thread.sleep(1000);
        return this.acceptStr + ",hello!";
    }
 public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService exec = Executors.newCachedThreadPool(); // 创建线程池
        // 向里面扔任务并执行该任务,同时返回一个包含call()方法返回值的Featured对象
        CallableImpl impl=new CallableImpl(“afei");
        Future<String> future=exec.submit(impl); 
        System.out.println(future.get()); //打印线程(任务)执行的结果
        exec.shutdown();// 关闭线程池后不接受新任务,已经在线程池的任务会被执行完
    }
}
3、controler方法中直接返回Callable对象或其派对象
@RestController
public class IAsyncController {
    private Logger logger=LoggerFactory.getLogger(getClass());
@PostMapping(
"/async/back") public Callable<String> back(){ logger.info("主线程开始"); Callable<String> c=new Callable<String>() { @Override public String call() throws Exception { // TODO Auto-generated method stub logger.info("副线程开始等待1s..."); Thread.sleep(1000); logger.info("副线程结束等待"); return "afei"; } }; logger.info("主线程结束并返回"); return c;//启动副线程并返回call()的返回值 } }

 

 

Runnable的3种启动线程的方式:
1、继承Thread类
public class Test extends Thread{
  public void run(){
   //操作临界资源
  }
   public static void main(String[] args){
       Test t=new Test();
       t.start();//启动线程
  } 
}
2、继承Runnable接口
public class Test implements Runnable{
  public void run(){
   //操作临界资源
  }
   public static void main(String[] args){
        Test t=new Test(); 
        Thread thread=new Thread(t); 
        thread.start();//启动线程
  } 
}
3、无名线程
public class Test{
   public static void main(String[] args){
       new Thread(()->{  //启动一个线程
            System.out.pritln("启动一个线程);
        }).start();
  } 
}    

 

转载于:https://www.cnblogs.com/afei1759/p/11415813.html

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值