Callable是一个接口
    两种方式是手动创建线程:thread类和runnable接口,但是这两个创建方式缺少一个功能,当线程终止的时候(run方法运行结束)的时候,我们无法得到返回值,为了支持这个功能,Java中提供了一个Callable接口。

    如果需要完成并且获得结果就使用call()方法,注意:不能使用Callable创建线程,只能使用Runnable创建线程
    call方法会抛出一个异常,run没有异常
    为实现Callable接口必须重写call方法。

    call方法需要注意的问题:
    定义一个线程执行的目标逻辑

    1. 定义线程执行的目标:
      这里我们是用卖票的案例模拟
    2. 向线程池提交任务:
      a. F<?> submit((Runnable task)):接收一个Runnable接口实现类, 执行线程的目标

      b. Future submit(Callable task):接收的是一个Callable接口实现类,执行线程目标
      Future:任务的结果
      V get()throws:ExecutionException, InterruptedException :返回的是一个call 的结果

    1. package Test22_Demo.Demo02;/*
    2. @create 2020--12--14--16:29
    3. */
    4. /**
    5. * 这是一个任务类
    6. * 使用第二种方式 - 实现Runnable接口
    7. */
    8. public class Ticket implements Runnable{
    9. //定义车票
    10. private int number = 100;
    11. //卖票逻辑
    12. @Override
    13. public void run() {
    14. //模拟车站不停的买票
    15. while (true) {
    16. //有票就卖
    17. if (number > 0) {
    18. System.out.println(Thread.currentThread().getName() + "正在销售第" + (number--) + "票");
    19. } else {
    20. //没有票了
    21. break;
    22. }
    23. }
    24. }
    25. }
    1. package Test22_Demo.Demo02;/*
    2. @create 2020--12--15--10:03
    3. */
    4. import java.util.concurrent.Callable;
    5. public class MyCallable implements Callable {
    6. @Override
    7. public Object call() throws Exception {
    8. return "我是线程任务的返回值结果";
    9. }
    10. }
    1. package Test22_Demo.Demo02;/*
    2. @create 2020--12--15--9:32
    3. */
    4. import Test22_Demo.Demo01.Ticket;
    5. import java.util.concurrent.ExecutionException;
    6. import java.util.concurrent.ExecutorService;
    7. import java.util.concurrent.Executors;
    8. import java.util.concurrent.Future;
    9. public class ThreadPoolDemo {
    10. public static void main(String[] args) throws ExecutionException, InterruptedException {
    11. //实例化线程
    12. ExecutorService threadDemo = Executors.newFixedThreadPool(3);
    13. //创建线程的执行目标
    14. Ticket ticket = new Ticket();
    15. /*threadDemo.submit(ticket);
    16. threadDemo.submit(ticket);
    17. threadDemo.submit(ticket);
    18. threadDemo.submit(ticket);
    19. threadDemo.submit(ticket);*/
    20. //利用Callable接口返回Future,没有返回值的run方法,返回的是null,没有意义
    21. Future<?> submit = threadDemo.submit(ticket);
    22. System.out.println(submit.get());
    23. //创建带有返回值的线程执行目标
    24. MyCallable callable = new MyCallable();
    25. //向线程中提交任务,并且返回线程目标的执行结果
    26. Future<String> future1 = threadDemo.submit(callable);
    27. Future<String> future2 = threadDemo.submit(callable);
    28. Future<String> future3 = threadDemo.submit(callable);
    29. //冲执行的结果返回call的具体值
    30. String result1 = future1.get();
    31. String result2 = future1.get();
    32. String result3 = future1.get();
    33. System.out.println(result1);
    34. System.out.println(result2);
    35. System.out.println(result3);
    36. //在适当的时候可以关闭线程池,一般不关闭 - 因为反而会影响性能
    37. //意味着线程池中的所有的线程都能销毁
    38. //threadPool。shutdown();
    39. }
    40. }