乐趣区

并发编程之Callable异步Future模式

Callable

在 Java 中,创建线程一般有两种方式,一种是继承 Thread 类,一种是实现 Runnable 接口。然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果。我们一般只能采用共享变量或共享存储区以及线程通信的方式实现获得任务结果的目的。

不过,Java 中,也提供了使用 Callable 和 Future 来实现获取任务结果的操作。Callable 用来执行任务,产生结果,而 Future 用来获得结果。

Callable 接口的定义如下:

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 接口不同之处在于,call 方法带有泛型返回值 V。

Future 模式

Future 模式的核心在于:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑

Futrure 模式: 对于多线程,如果线程 A 要等待线程 B 的结果,那么线程 A 没必要等待 B,直到 B 有结果,可以先拿到一个未来的 Future,等 B 有结果是再取真实的结果。

在多线程中经常举的一个例子就是:网络图片的下载,刚开始是通过模糊的图片来代替最后的图片,等下载图片的线程下载完图片后在替换。而在这个过程中可以做一些其他的事情。

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


/** 
 * @author wn: 
 * @version 上午 16:53:57 
 * 类说明 
 */
public class ThreadCallTest {public static void main(String[]args){ExecutorService executor=Executors.newCachedThreadPool();
    Task task=new Task();
    Future<Integer> result=executor.submit(task);
    if (executor != null)
            executor.shutdown();
  
    try {System.out.println("call result"+result.get());
    } catch (InterruptedException e) {e.printStackTrace();
    } catch (ExecutionException e) {e.printStackTrace();
    }
    System.out.println("over");
  
  }
}

class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {System.out.println("3. 开始 ....");
        Thread.sleep(3000);
        System.out.println("4. 结束 ....");
        return "xyz";
    }
}

当 Task 启动后不影响主线程运行,result.get() 会等待 3 秒后返回结果 xyz

Future 常用方法

V get():获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。

V get(Long timeout , TimeUnit unit):获取异步执行结果,如果没有结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的 timeout 时间,该方法将抛出异常。

boolean isDone():如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回 true。=> result.isDone()

boolean isCanceller():如果任务完成前被取消,则返回 true。

boolean cancel(boolean mayInterruptRunning):如果任务还没开始,执行 cancel(…) 方法将返回 false;如果任务已经启动,执行 cancel(true) 方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回 true;

当任务已经启动,执行 cancel(false) 方法将不会对正在执行的任务线程产生影响 (让线程正常执行到完成),此时返回 false;

当任务已经完成,执行 cancel(…) 方法将返回 false。mayInterruptRunning 参数表示是否中断执行中的线程。

实际上 Future 提供了 3 种功能:

  • (1)能够中断执行中的任务
  • (2)判断任务是否执行完成
  • (3)获取任务执行完成后的结果

个人博客 蜗牛

退出移动版