小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Future和Callable的使用總結(jié)

 創(chuàng)始元靈6666 2022-06-17 發(fā)布于河北

在默認的情況下,線程Thread對象不具有返回值的功能,如果在需要取得返回值的情況下是極為不方便的,但在Java1.5的并發(fā)包中可以使用Future和Callable來使線程具有返回值的功能。

1.Future和Callable的介紹

接口Callable與線程功能密不可分,但和Runnable的主要區(qū)別為:

(1) 接口Callable的call()方法可以有返回值,但Runnable接口的run()方法沒有返回值。

(2) Callable接口的call()方法可以聲明拋出異常,而Runnable接口的run()方法不可以聲明拋出異常。

執(zhí)行完Callable接口中的任務(wù)后,返回值是通過Future接口進行獲得的。

2.方法get()結(jié)合ExecutorService中的submit(Callable<T>)的使用

方法submit(Callable<T>)可以執(zhí)行參數(shù)為Callable的任務(wù),方法get()用于獲得返回值,示例如下:

  1. package mycallable;
  2. import java.util.concurrent.Callable;
  3. public class MyCallable implements Callable<String> {
  4. private int age;
  5. public MyCallable(int age) {
  6. super();
  7. this.age = age;
  8. }
  9. public String call() throws Exception {
  10. Thread.sleep(8000);
  11. return "返回值 年齡是:" + age;
  12. }
  13. }
  1. package test.run;
  2. import java.util.concurrent.ExecutionException;
  3. import java.util.concurrent.Future;
  4. import java.util.concurrent.LinkedBlockingDeque;
  5. import java.util.concurrent.ThreadPoolExecutor;
  6. import java.util.concurrent.TimeUnit;
  7. import mycallable.MyCallable;
  8. public class Run {
  9. public static void main(String[] args) throws InterruptedException {
  10. try {
  11. MyCallable callable = new MyCallable(100);
  12. ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 5L,
  13. TimeUnit.SECONDS, new LinkedBlockingDeque());
  14. Future<String> future = executor.submit(callable);
  15. System.out.println("main A " + System.currentTimeMillis());
  16. System.out.println(future.get());
  17. System.out.println("main B " + System.currentTimeMillis());
  18. } catch (ExecutionException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }

3.方法get()結(jié)合ExecutorService中的submit(Runnable)和isDone()的使用

方法submit()不僅可以傳入Callable對象,也可以傳入Runnable對象,說明submit方法支持有返回值和無返回值的功能。如果submit方法傳入Callable接口則可以有返回值,如果傳入Runnable則無返回值,打印的結(jié)果就是null。方法get()具有阻塞特性,而isDone()方法無阻塞特性。

  1. package test.run;
  2. import java.util.concurrent.ExecutionException;
  3. import java.util.concurrent.ExecutorService;
  4. import java.util.concurrent.Executors;
  5. import java.util.concurrent.Future;
  6. /**
  7. * 如果submit方法傳入Callable接口則可以有返回值,如果傳入Runnable則無返回值,打印的結(jié)果就是null。方法get()具有阻塞特性,而isDone()方法無阻塞特性
  8. * @author linhaiy
  9. * @date 2019.03.06
  10. */
  11. public class Run {
  12. public static void main(String[] args) {
  13. try {
  14. Runnable runnable = new Runnable() {
  15. @Override
  16. public void run() {
  17. System.out.println("打印的信息");
  18. }
  19. };
  20. ExecutorService executorRef = Executors.newCachedThreadPool();
  21. Future future = executorRef.submit(runnable);
  22. System.out.println(future.get() + " " + future.isDone());
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. } catch (ExecutionException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }

4.使用ExecutorService接口中的方法submit(Runnable,T result)

方法submit(Runnable,T result)的第2個參數(shù)result可以作為執(zhí)行結(jié)果的返回值,而不需要使用get()方法來進行獲得。

  1. package entity;
  2. public class Userinfo {
  3. private String username;
  4. private String password;
  5. public Userinfo() {
  6. super();
  7. }
  8. public Userinfo(String username, String password) {
  9. super();
  10. this.username = username;
  11. this.password = password;
  12. }
  13. public String getUsername() {
  14. return username;
  15. }
  16. public void setUsername(String username) {
  17. this.username = username;
  18. }
  19. public String getPassword() {
  20. return password;
  21. }
  22. public void setPassword(String password) {
  23. this.password = password;
  24. }
  25. }
  1. package myrunnable;
  2. import entity.Userinfo;
  3. public class MyRunnable implements Runnable {
  4. private Userinfo userinfo;
  5. public MyRunnable(Userinfo userinfo) {
  6. super();
  7. this.userinfo = userinfo;
  8. }
  9. @Override
  10. public void run() {
  11. userinfo.setUsername("usernameValue");
  12. userinfo.setPassword("passwordValue");
  13. }
  14. }
  1. package test;
  2. import java.util.concurrent.ExecutionException;
  3. import java.util.concurrent.Future;
  4. import java.util.concurrent.FutureTask;
  5. import java.util.concurrent.LinkedBlockingDeque;
  6. import java.util.concurrent.ThreadPoolExecutor;
  7. import java.util.concurrent.TimeUnit;
  8. import myrunnable.MyRunnable;
  9. import entity.Userinfo;
  10. public class Test {
  11. FutureTask abc; //接口Future的實現(xiàn)類
  12. public static void main(String[] args) {
  13. try {
  14. Userinfo userinfo = new Userinfo();
  15. MyRunnable myrunnable = new MyRunnable(userinfo);
  16. ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 10,
  17. TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
  18. Future<Userinfo> future = pool.submit(myrunnable, userinfo);
  19. System.out.println(future);
  20. System.out.println("begin time=" + System.currentTimeMillis());
  21. userinfo = future.get();
  22. System.out.println("get value " + userinfo.getUsername() + " "
  23. + userinfo.getPassword());
  24. System.out.println(" end time=" + System.currentTimeMillis());
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. } catch (ExecutionException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }

5.方法cancel(boolean mayInterruptIfRunning) 和isCancelled()的使用

方法cancel(boolean mayInterruptIfRunning)的參數(shù)mayInterruptIfRunning的作用是:如果線程正在運行則是否中斷正在運行的線程,在代碼中需要使用if(Thread.currentThread().isInterrupted())進行配合。

方法cancel()的返回值代表發(fā)送取消任務(wù)的命令是否成功完成。

6.方法get(long timeout,TimeUnit unit)的使用

方法get(long timeout,TimeUnit unit)的作用是在指定的最大時間內(nèi)等待獲得返回值。

  1. package mycallable;
  2. import java.util.concurrent.Callable;
  3. public class MyCallable implements Callable<String> {
  4. public String call() throws Exception {
  5. Thread.sleep(10000); //目的是為了在指定時間內(nèi)獲取不到返回值
  6. System.out.println("sleep 10秒執(zhí)行完了!");
  7. return "anyString";
  8. }
  9. }
  1. package test.run;
  2. import java.util.concurrent.ExecutionException;
  3. import java.util.concurrent.Future;
  4. import java.util.concurrent.LinkedBlockingDeque;
  5. import java.util.concurrent.ThreadPoolExecutor;
  6. import java.util.concurrent.TimeUnit;
  7. import java.util.concurrent.TimeoutException;
  8. import mycallable.MyCallable;
  9. public class Run {
  10. public static void main(String[] args) {
  11. try {
  12. MyCallable callable = new MyCallable();
  13. ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 5L,
  14. TimeUnit.SECONDS, new LinkedBlockingDeque());
  15. System.out.println("begin " + System.currentTimeMillis());
  16. Future<String> future = executor.submit(callable);
  17. System.out.println("返回值" + future.get(5, TimeUnit.SECONDS));
  18. System.out.println(" end " + System.currentTimeMillis());
  19. } catch (InterruptedException e) {
  20. System.out.println("進入catch InterruptedException");
  21. e.printStackTrace();
  22. } catch (ExecutionException e) {
  23. System.out.println("進入catch ExecutionException");
  24. e.printStackTrace();
  25. } catch (TimeoutException e) {
  26. System.out.println("進入catch TimeoutException");
  27. e.printStackTrace();
  28. }
  29. }
  30. }

7.自定義拒絕策略RejectedExecutionHandler接口的使用

接口RejectedExecutionHandler的主要作用是當線程池關(guān)閉后依然有任務(wù)要執(zhí)行時,可以實現(xiàn)一些處理。

  1. package com.executionhandler;
  2. import java.util.concurrent.FutureTask;
  3. import java.util.concurrent.RejectedExecutionHandler;
  4. import java.util.concurrent.ThreadPoolExecutor;
  5. public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
  6. public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
  7. System.out.println(((FutureTask) r).toString() + " 被拒絕!");
  8. }
  9. }
  1. package com.executionhandler;
  2. public class MyRunnable implements Runnable {
  3. private String username;
  4. public MyRunnable(String username) {
  5. super();
  6. this.username = username;
  7. }
  8. public void run() {
  9. System.out.println(username + " 在運行!");
  10. }
  11. }
  1. package com.executionhandler;
  2. import java.util.concurrent.ExecutorService;
  3. import java.util.concurrent.Executors;
  4. import java.util.concurrent.ThreadPoolExecutor;
  5. public class Run {
  6. public static void main(String[] args) {
  7. ExecutorService service = Executors.newCachedThreadPool();
  8. ThreadPoolExecutor executor = (ThreadPoolExecutor) service;
  9. executor.setRejectedExecutionHandler(new MyRejectedExecutionHandler());
  10. service.submit(new MyRunnable("A"));
  11. service.submit(new MyRunnable("B"));
  12. service.submit(new MyRunnable("C"));
  13. executor.shutdown();
  14. service.submit(new MyRunnable("D"));
  15. }
  16. }

8.方法execute()與submit()的區(qū)別

(1) 方法execute()沒有返回值,而submit()方法可以有返回值。

(2) 方法execute()在默認的情況下異常直接拋出,不能捕獲,但可以通過自定義ThreadFactory的方式進行捕獲,而submit()方法在默認的情況下,可以catch Execution-Exeception捕獲異常

9.驗證Future的缺點

  1. package mycallable;
  2. import java.util.concurrent.Callable;
  3. public class MyCallable implements Callable<String> {
  4. private String username;
  5. private long sleepValue;
  6. public MyCallable(String username, long sleepValue) {
  7. super();
  8. this.username = username;
  9. this.sleepValue = sleepValue;
  10. }
  11. @Override
  12. public String call() throws Exception {
  13. System.out.println(username);
  14. Thread.sleep(sleepValue);
  15. return "return " + username;
  16. }
  17. }
  1. package test;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.concurrent.Callable;
  5. import java.util.concurrent.ExecutionException;
  6. import java.util.concurrent.Future;
  7. import java.util.concurrent.LinkedBlockingDeque;
  8. import java.util.concurrent.ThreadPoolExecutor;
  9. import java.util.concurrent.TimeUnit;
  10. import mycallable.MyCallable;
  11. public class Test {
  12. public static void main(String[] args) {
  13. try {
  14. MyCallable callable1 = new MyCallable("username1", 5000);
  15. MyCallable callable2 = new MyCallable("username2", 4000);
  16. MyCallable callable3 = new MyCallable("username3", 3000);
  17. MyCallable callable4 = new MyCallable("username4", 2000);
  18. MyCallable callable5 = new MyCallable("username5", 1000);
  19. List<Callable> callableList = new ArrayList<Callable>();
  20. callableList.add(callable1);
  21. callableList.add(callable2);
  22. callableList.add(callable3);
  23. callableList.add(callable4);
  24. callableList.add(callable5);
  25. List<Future> futureList = new ArrayList<Future>();
  26. ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
  27. new LinkedBlockingDeque<Runnable>());
  28. for (int i = 0; i < 5; i++) {
  29. futureList.add(executor.submit(callableList.get(i)));
  30. }
  31. System.out.println("run first time= " + System.currentTimeMillis());
  32. for (int i = 0; i < 5; i++) {
  33. System.out.println(futureList.get(i).get() + " " + System.currentTimeMillis());
  34. }
  35. // 按順序打印的效果
  36. // 說明一個Future對應(yīng)指定的一個Callable
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. } catch (ExecutionException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. }

總結(jié):Future和Callable這兩個接口的優(yōu)點就是從線程中返回數(shù)據(jù)以便進行后期的處理,但是FutureTask類也有其自身的缺點,就是阻塞性。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多