实现Callable接口

与使用Runnable相比,Callable接口更强大

  • 相比run方法,可以有返回值
  • 方法可以抛出异常
  • 支持泛型的返回值
  • 需要借助FutureTask类,比如获取返回结果

Future接口

  • 可以对具体Runnable、Callable任务的执行进行结构进行取消、查询是否完成、获取结果等
  • FutureTask是Future接口的唯一实现类
  • FutureTask同时实现了Runnable、Future接口。它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值
  1. import java.util.concurrent.Callable;
  2. import java.util.concurrent.ExecutionException;
  3. import java.util.concurrent.FutureTask;
  4. /**
  5. * 通过实现Callable接口来创建线程
  6. * @author hsy
  7. * @date 2022/12/20
  8. */
  9. //1.创建一个Callable的实现类
  10. class NumThread implements Callable{
  11. //2.实现call方法,将需要执行的操作声明在call中
  12. @Override
  13. public Object call() throws Exception {
  14. int sum = 0;
  15. for (int i = 0; i < 100; i++) {
  16. if(i%2==0){
  17. //System.out.println(i);
  18. sum += i;
  19. }
  20. }
  21. return sum;
  22. }
  23. }
  24. public class ThreadNew {
  25. public static void main(String[] args) {
  26. //3.创建Callable接口实现类的对象
  27. NumThread numThread = new NumThread();
  28. //4.将此Callable接口实现类的对象作为参数传递到FutureTask的构造器中,创建FutureTask的对象
  29. FutureTask futureTask = new FutureTask(numThread);
  30. //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start
  31. new Thread(futureTask).start();
  32. try {
  33. //6.获取Callable中call方法的返回值
  34. Object sum = futureTask.get();
  35. System.out.println(sum);
  36. } catch (InterruptedException e) {
  37. throw new RuntimeException(e);
  38. } catch (ExecutionException e) {
  39. throw new RuntimeException(e);
  40. }
  41. }
  42. }

使用线程池

背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响较大

思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免重复创建、销毁、实现重复利用

好处:

  • 提高响应速度(减少了创建新线程的时间)
  • 降低资源内耗(重复利用线程池中的线程)
  • 便于线程管理
    • corePoolSize:核心池的大小
    • maximunPoolSize:最大线程数
    • keepAliveTime:线程没有任务时最多保持多长时间后会终止

线程池相关API

image.png

例子

  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.ThreadPoolExecutor;
  4. /**
  5. * 使用线程池创建线程
  6. * @author hsy
  7. * @date 2022/12/20
  8. */
  9. class NumberThread implements Runnable{
  10. @Override
  11. public void run() {
  12. for (int i = 0; i < 100; i++) {
  13. if(i%2==0){
  14. System.out.println(i);
  15. }
  16. }
  17. }
  18. }
  19. public class ThreadPool {
  20. public static void main(String[] args) {
  21. //1.提供指定线程数量的连接池
  22. ExecutorService service = Executors.newFixedThreadPool(10);
  23. //设置线程池的属性
  24. ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
  25. service1.setCorePoolSize(15);
  26. //2.执行指定的线程操作,需要提供实现Runnable接口或Callable接口实现类的对象
  27. service.execute(new NumberThread());//适合于Runnable
  28. //service.submit();//适合于Callable
  29. //关闭连接池
  30. service.shutdown();
  31. }
  32. }