• java Runnable、Callable、FutureTask 和线程池


    一:Runnable、Callable、FutureTask简介

    (1)Runnable:其中的run()方法没有返回值。

    ①.Runnable对象可以直接扔给Thread创建线程实例,并且创建的线程实例与Runnable绑定,线程实例调用start()方法时,Runnable任务就开始真正在线程中执行。

    ②.Runnable对象也可以直接扔给线程池对象的execute方法和submit方法,让线程池为其绑定池中的线程来执行。

    ③.Runnable对象也可以进一步封装成FutureTask对象之后再扔给线程池的execute方法和submit方法。

    (2)Callable:功能相比Runnable来说少很多,不能用来创建线程,也不能直接扔给线程池的execute方法,但是可以使用submit。其中的call方法有返回值,也进一步封装成Future,再由线程执行。

    (3)FutureTask:是对Runnable和Callable的进一步封装,并且这种任务是有返回值的,它的返回值存在FutureTask类的一个名叫outcome的数据成员中。(疑惑)那么为什么可以把没有返回值的Runnable也封装成FutureTask呢,马上我们会讨论这个问题。相比直接把Runnable和Callable扔给线程池,FutureTask的功能更多,它可以监视任务在池子中的状态。用Runnable和Callable创建FutureTask的方法稍有不同。

    (4)Runable 转换 Callable

      Callable<Object> callable = Executors.callable(new MyRunnable());
    

    (5)FutureTask 的使用

    FutureTask futureTask = new FutureTask(new CallableTask());
             new Thread(futureTask).start();//或者由线程池执行
    

    FutureTask类实现了RunnableFuture接口,而RunnableFuture接口又继承了Runnable接口和Future接口,所以FutureTask类本质上是Runnable接口的实现类,且兼具Future接口的特性,我们知道线程池的execute方法和submit方法都可以执行Runable任务,所以同样可以执行FutureTask任务。

    //FutureTask 构造函数
        public FutureTask(Callable<V> callable);
        public FutureTask(Runnable runnable, V result); 
    
     FutureTask类有一个done方法,该方法在任务执行完毕时自动回调,我们可以重写该方法并在该方法中调用get()方法获取任务执行的结果,并且因为任务已经执行完毕,此时调用get()方法可以直接得到结果,所以并不会阻塞线程。
    

    二:线程池

    (1)Executor 接口 只提供一个void execute(Runnable command),只能执行Runnable 任务,但是不能执行Callable 任务。所以提供了ExecutorService 接口。

    (2)ExecutorService 接口 其继承了Executor,提供了submit()方法重载可以执行Runnable 任务和Callable任务。ExecutorService 可以创建四种线程池
    ①newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

       ExecutorService  singleThreadExecutor = Executors.newSingleThreadExecutor(); //返回ExecutorService
       singleThreadExecutor .submit() //可以是Runable任务或者Callable任务
       
    

    ②newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

       ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); //返回ExecutorService
       fixedThreadPool .submit();//可以是Runable任务或者Callable任务
    

    ③newCachedThreadPool创建一个可缓存线程池,如果处理需求超过线程池长度,可灵活回收空闲线程,若无可回收,则新建线程,线程池无限大,举例:要执行两个人,如果在第二个任务执行前,第一个任务已经完成,则会复用第一个线程去执行第二个任务,不创建新的线程。

       ExecutorService cachedThreadPool = Executors.newCachedThreadPool();  //返回ExecutorService
      cachedThreadPool.submit();// 可以是Runable任务或者Callable任务
    

    **④newScheduledThreadPool **创建一个定长线程池,支持定时及周期性任务执行。

       ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); //返回ScheduledExecutorService  其继承了ExecutorService
       scheduledThreadPool .scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
       
       /*
       ScheduledExecutorService接口 主要有以下方法,由ScheduledThreadPoolExecutor实现
        1,<V> ScheduledFuture<V>	schedule(Callable<V> callable, long delay, TimeUnit unit)  //执行Callable
        2,ScheduledFuture<?>	schedule(Runnable command, long delay, TimeUnit unit)  //执行Runable
        3,ScheduledFuture<?>	scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)  //以任务执行开始时间为起点,过多久执行一次
        4,ScheduledFuture<?>	scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) //以任务执行结束时间为起点,过多久执行一次
      */
       
    
  • 相关阅读:
    Linux下的游戏及模拟器
    [Java]学习Java(3)数组、字符串
    [Javascript]Event属性
    下载文件名乱码
    比那 施氏食狮史 还要强的文章
    [Javascript]脚本学习(1)
    [Java]学习Java(2)基本类型与对象
    [Java]学习Java(1)运算符&语句&类
    LumaQQ开发文档
    Extensions for FireFox
  • 原文地址:https://www.cnblogs.com/hts-technology/p/9300971.html
Copyright © 2020-2023  润新知