Callable 和 Runnable 的 区别(简单分析


runable的异步是不需要返回,主线程执行后续代码,主线程可以直接结束--由此体现异步
callable的异步是可以返回,主线程需要等待子线程返回,一般开启多个子线程--由此体现异步

1、区别

不同点 Callable Runnable
方法  V call()  throws Exception run()
返回值  V call()  有返回值 void run()  没有返回值
异常 call() 可以抛出受检查的异常 run() 不能抛出异常
启动

1、使Thread 来包装,使用start() 启动

2、提交给 线程池 ExecuteService.submit() 启动

1、使Thread 来包装,使用start() 启动

2、提交给 线程池 ExecuteService.submit() 和execute() 启动

 

注意:execute() 只接收Runnable实现类,且没有返回值

 


2、Callable示例如下: 

 
  1. class CallableImpl implements Callable {

  2. private int age;

  3.  
  4. public CallableImpl(int age) {

  5. this.age = age;

  6. }

  7.  
  8. // 具体逻辑在这里实现,并有一个返回值

  9. public Object call() throws Exception {

  10. Thread.currentThread().sleep(new Random().nextInt(1000));

  11. String ss="";

  12. if (age < 0) {

  13. ss="age = " + age + ", 输入年龄有误";

  14. } else if (age < 20) {

  15. ss="age = " + age + ", 你好,年轻人";

  16. } else if (age < 40) {

  17. ss= "age = " + age + ", 你好,中年人";

  18. } else {

  19. ss= "age = " + age + ", 你好,老年人";

  20. }

  21. System.out.println(ss);

  22. return ss;

  23. }

  24. }

  25.  
  26. public class CallableTest {

  27.  
  28. public static void main(String[] args) throws InterruptedException, ExecutionException {

  29.  
  30. // 建立一个线程池

  31. ExecutorService exc = Executors.newFixedThreadPool(3);

  32. // 存放返回的结果

  33. List> futures = new ArrayList>();

  34.  
  35. for (int i = -10; i < 50; i += 3) {

  36. CallableImpl call = new CallableImpl(i);

  37. // 执行callable的call方法,并有返回值

  38. Future future = exc.submit(call);

  39. futures.add(future);

  40.  
  41. }

  42. System.out.println("等待结果:");

  43. for (Future future : futures) {

  44. // 这里调用get()方法会阻塞当前线程,直到得到返回结果

  45. System.out.println("----------- "+future.get());

  46. // if (future.isDone()) {

  47. // System.out.println(future.get());

  48. // } else {

  49. // System.out.println("Future result is not yet complete");

  50. // }

  51. }

  52. System.out.println("结束...");

  53. //Thread.currentThread().sleep(1000*30);

  54. exc.shutdown();

  55. }

  56. }


结果:

等待结果:
age = -10, 输入年龄有误
----------- age = -10, 输入年龄有误
age = -4, 输入年龄有误
age = -1, 输入年龄有误
age = 2, 你好,年轻人
age = -7, 输入年龄有误
----------- age = -7, 输入年龄有误
----------- age = -4, 输入年龄有误
----------- age = -1, 输入年龄有误
----------- age = 2, 你好,年轻人
age = 11, 你好,年轻人
age = 5, 你好,年轻人
----------- age = 5, 你好,年轻人
age = 8, 你好,年轻人
----------- age = 8, 你好,年轻人
----------- age = 11, 你好,年轻人
age = 17, 你好,年轻人
age = 14, 你好,年轻人
----------- age = 14, 你好,年轻人
----------- age = 17, 你好,年轻人
age = 26, 你好,中年人
age = 23, 你好,中年人
age = 20, 你好,中年人
----------- age = 20, 你好,中年人
----------- age = 23, 你好,中年人
----------- age = 26, 你好,中年人
age = 35, 你好,中年人
age = 32, 你好,中年人
age = 41, 你好,老年人
age = 29, 你好,中年人
----------- age = 29, 你好,中年人
----------- age = 32, 你好,中年人
----------- age = 35, 你好,中年人
age = 38, 你好,中年人
----------- age = 38, 你好,中年人
----------- age = 41, 你好,老年人
age = 44, 你好,老年人
----------- age = 44, 你好,老年人
age = 47, 你好,老年人
----------- age = 47, 你好,老年人
结束...

 

3、Runnable示例:

 
  1. public class LiftOff implements Runnable {

  2.  
  3. protected int countDown = 10;

  4. private static int taskCount = 0;

  5. private final int id = taskCount++;

  6.  
  7. public LiftOff() {

  8.  
  9. }

  10.  
  11. public LiftOff(int countDown) {

  12. this.countDown = countDown;

  13. }

  14.  
  15. public String status() {

  16. return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff! ") + ")";

  17. }

  18.  
  19. @Override

  20. public void run() {

  21. while (countDown-- > 0) {

  22. System.out.print(status());

  23. Thread.yield();

  24. }

  25. System.out.println();

  26. }

  27.  
  28. public static void main(String[] args) {

  29. ExecutorService exec = Executors.newFixedThreadPool(1);

  30. for (int i = 0; i < 5; i++) {

  31. exec.execute(new LiftOff());

  32. }

  33. exec.shutdown();

  34. }

  35. }

 

 

 

注意ExecutorService 在Callable中使用的是submit(), 在Runnable中使用的是 execute()。

你可能感兴趣的:(Callable 和 Runnable 的 区别(简单分析)