Juc01_多线程概述、四种实现方式、常用方法API、生命周期、买票案例、synchronized锁(二)

简介: ③. Callable接口(创建线程)

③. Callable接口(创建线程)


  • ①. Callable接口中的call方法和Runnable接口中的run方法的区别


  1. 是否有返回值(Runnable接口没有返回值 Callable接口有返回值)


  1. 是否抛异常(Runnable接口不会抛出异常 Callable接口会抛出异常)


  1. 落地方法不一样,一个是call() ,一个是run()


微信图片_20220106173548.png


  • ②. Future接口概述


  1. FutureTask是Future接口的唯一的实现类


  1. FutureTask同时实现了Runnable、Future接口。它既可以作为Runnable被线程执行,又可以作为Futrue得到Callable的返回值


微信图片_20220106173612.png


  /*
  创建线程的方式三: 实现callable接口 ---JDK 5.0 新增
  1.创建一个实现Callable接口的实现类
  2.实现call方法,将此线程需要执行的操作声明在call()中
  3.创建callable接口实现类的对象
  4.将此callable的对象作为参数传入到FutureTask构造器中,创建FutureTask的对象
  5.将FutureTask对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用star
  6.获取callable接口中call方法的返回值
  * */
  public class ThreadNew {
      public static void main(String[] args) {
          //3.创建callable接口实现类的对象
          NumThead m=new NumThead();
          //4.将此callable的对象作为参数传入到FutureTask构造器中,创建FutureTask的对象
          FutureTask futureTask = new FutureTask(m);
          //5.将FutureTask对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()方法
          //FutureTask类继承了Runnable接口
          //new Runnable = futrueTask;
          new Thread(futureTask).start();
          //6.获取callable接口中call方法的返回值
          try {
              //get()方法返回值即为FutureTask构造器参数callable实现类重写的call方法的返回值
              Object sum = futureTask.get();
              System.out.println("总和是:"+sum);
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  //1.创建一个实现Callable接口的实现类
  class  NumThead implements Callable{
     // class  NumThead implements Callable<Integer>{
      //2.实现call方法,将此线程需要执行的操作声明在call()中
      @Override
      public Object call() throws Exception {
      //public Integer call() throws Exception {
          int sum=0;
          for(int i=1;i<=100;i++){
              System.out.println(i);
              sum+=i;
          }
          return sum;
      }
  }


③.FutureTask原理解析


有了Runnable,为什么还要有Callable接口?我们假设一共有四个程序需要执行,第三个程序时间很长 | Runnable接口会按照顺序去执行,会依次从上到下去执行,会等第三个程序执行完毕,才去执行第四个 | Callable接口会把时间长的第三个程序单独开启一个线程去执行,第1、2、4 线程执行不受影响


比如主线程让一个子线程去执行任务,子线程可能比较耗时,启动子线程开始执行任务。子线程就去做其他的事情,过一会儿才去获取子任务的执行结果


微信图片_20220106173642.png


    例子:
  (1). 老师上着课,口渴了,去买水不合适,讲课线程继续,我可以单起个线程找班长帮忙
  买水,水买回来了放桌上,我需要的时候再去get。
  (2). 4个同学,A算1+20,B算21+30,C算31*到40,D算41+50,是不是C的计算量有点大啊,
  FutureTask单起个线程给C计算,我先汇总ABD,最后等C计算完了再汇总C,拿到最终结果
  (3). 高考:会做的先做,不会的放在后面做


  • ④. 注意事项


  1. get( )方法建议放在最后一行,防止线程阻塞(一旦调用了get( )方法,不管是否计算完成都会阻塞)


  1. 一个FutureTask,多个线程调用call( )方法只会调用一次


  1. 如果需要调用call方法多次,则需要多个FutureTask


public class CallableDemo  {
    public static void main(String[] args) throws Exception{
        CallAble c=new CallAble();
        FutureTask<Integer> futureTask=new FutureTask<>(c);
        new Thread(futureTask,"线程A").start();
        new Thread(futureTask,"线程B").start();
        Integer integer = futureTask.get();
        System.out.println("integer = " + integer);
    }
}
class CallAble implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("欢迎你调用call方法");
        return 6;
    }
}


微信图片_20220106173725.png


  • ⑤. isDone()轮询(后面我们会用CompletableFuture来解决get( )阻塞的问题)


  1. 轮询的方式会消耗无畏的CPU资源,而且也不见得能及时地得到计算的结果


  1. 如果想要异步获取结果,通常都会以轮询的方式去获取结果,尽量不要阻塞


public class FutureTaskTest {
    public static void main(String[] args) throws Exception{
        FutureTask futureTask = new FutureTask(()->{
            try { TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+"\t"+"coming......");
            return 1024;
        });
        new Thread(futureTask).start();
        //1.果futureTask.get()放到main线程前面,会导致main线程阻塞
        //Object o = futureTask.get();
        /*Object o = futureTask.get();//不见不散,只要出现了get()方法就会阻塞
        System.out.println("不见不散,只要出现了get()方法就会阻塞,获取到的值为:"+o);*/
        //2.过时不候
//        System.out.println(Thread.currentThread().getName()+"\t"+"线程来了.....");
//        Object o2 = futureTask.get(2L, TimeUnit.SECONDS);
        //3.使用轮询
        while(true){
            if(futureTask.isDone()){
                System.out.println("使用轮询来解决,值为:"+futureTask.get());
                break;
            }else{
                System.out.println("阻塞中**********");
            }
        }
    }
}
相关文章
|
缓存 负载均衡 监控
微服务架构下的电商API接口设计:策略、方法与实战案例
本文探讨了微服务架构下的电商API接口设计,旨在打造高效、灵活与可扩展的电商系统。通过服务拆分(如商品、订单、支付等模块)和标准化设计(RESTful或GraphQL风格),确保接口一致性与易用性。同时,采用缓存策略、负载均衡及限流技术优化性能,并借助Prometheus等工具实现监控与日志管理。微服务架构的优势在于支持敏捷开发、高并发处理和独立部署,满足电商业务快速迭代需求。未来,电商API设计将向智能化与安全化方向发展。
645 102
|
JSON 数据可视化 API
Python 中调用 DeepSeek-R1 API的方法介绍,图文教程
本教程详细介绍了如何使用 Python 调用 DeepSeek 的 R1 大模型 API,适合编程新手。首先登录 DeepSeek 控制台获取 API Key,安装 Python 和 requests 库后,编写基础调用代码并运行。文末包含常见问题解答和更简单的可视化调用方法,建议收藏备用。 原文链接:[如何使用 Python 调用 DeepSeek-R1 API?](https://apifox.com/apiskills/how-to-call-the-deepseek-r1-api-using-python/)
|
11月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
503 1
|
12月前
|
人工智能 API 开发者
图文教程:阿里云百炼API-KEY获取方法,亲测全流程
本文详细介绍了如何获取阿里云百炼API-KEY,包含完整流程与截图指引。需先开通百炼平台及大模型服务,再通过控制台创建并复制API-KEY。目前平台提供千万tokens免费额度,适合开发者快速上手使用。
7135 5
|
供应链 API
案例分享:API如何助力小型电商实现月销售额翻倍
&quot;悦居生活&quot;通过接入支付、库存、营销及物流API,优化运营流程,解决库存滞后、营销低效、物流体验差等问题,实现库存周转率提升152%、会员复购率增长128%、月销售额突破32万元。
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
1420 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
JSON 安全 API
Python调用API接口的方法
Python调用API接口的方法
2376 5
|
供应链 安全 NoSQL
PHP 互斥锁:如何确保代码的线程安全?
在多线程和高并发环境中,确保代码段互斥执行至关重要。本文介绍了 PHP 互斥锁库 `wise-locksmith`,它提供多种锁机制(如文件锁、分布式锁等),有效解决线程安全问题,特别适用于电商平台库存管理等场景。通过 Composer 安装后,开发者可以利用该库确保在高并发下数据的一致性和安全性。
364 6
|
XML 数据可视化 API
商品详情数据实战案例,API接口系列
淘宝商品详情数据在电商领域具有广泛的应用价值,而淘宝商品详情API接口则为开发者提供了获取这些数据的重要途径。通过合理利用这些接口和数据,可以提升业务效率、优化用户体验,为电商行业的发展注入新的活力。
|
Java 关系型数据库 MySQL
【JavaEE“多线程进阶”】——各种“锁”大总结
乐/悲观锁,轻/重量级锁,自旋锁,挂起等待锁,普通互斥锁,读写锁,公不公平锁,可不可重入锁,synchronized加锁三阶段过程,锁消除,锁粗化