暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java线程之异步回调(Callback)

那些年的代码 2021-03-17
1719

●介绍 

    有时候执行一个任务需要很长时间,单线程下线程会处于阻塞状态。这个时候我们会考虑一种非阻塞的处理模式。非阻塞任务在任何编程语言里都必不可少,Java也不例外。多线程就是一个很好的解决办法。 
    但是多线程是异步处理,异步就意味着不知道处理结果,如果我们需要知道处理结果的时候应该怎么办呢?笔者介绍下面两种方法 


●Callback 

回调一般是异步处理的一种技术。一个回调是被传递到并且执行完该方法。这种方式只能异步回调,如果需要同步等待线程处理结果可以使用下面介绍的Futures

  1. package callback;

  2. import java.util.Map;

  3. public interface ICallback {

  4. public void callback(Map<String, Object> params);

  5. }


  1. package callback;

  2. import java.util.HashMap;

  3. import java.util.Map;

  4. import java.util.concurrent.ExecutorService;

  5. import java.util.concurrent.Executors;

  6. /**

  7. * Callback

  8. * 回调一般是异步处理的一种技术。

  9. * 一个回调是被传递到并且执行完该方法。这种方式只能异步回调,

  10. * 如果需要同步等待线程处理结果可以使用下面介绍的Futures

  11. */

  12. public class NettyTest1 {

  13. static ExecutorService es = Executors.newFixedThreadPool(2);

  14. public static void doStm(final ICallback callback) {

  15. // 初始化一个线程

  16. Thread t = new Thread() {

  17. public void run() {

  18. // 这里是业务逻辑处理

  19. System.out.println("子线任务执行:"+Thread.currentThread().getId());

  20. // 为了能看出效果 ,让当前线程阻塞5秒

  21. try {

  22. Thread.sleep(1000);

  23. } catch (InterruptedException e) {

  24. e.printStackTrace();

  25. }

  26. // 处理完业务逻辑,

  27. Map<String, Object> params = new HashMap<String, Object>();

  28. params.put("a1", "这是我返回的参数字符串...");

  29. callback.callback(params);

  30. };

  31. };

  32. es.execute(t);

  33. //一定要调用这个方法,不然executorService.isTerminated()永远不为true

  34. es.shutdown();

  35. }

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

  37. // 内部类 等价于 ICallback callbck = new ICallback的实现类();

  38. // 新手如果对内部类的写法有疑惑可以查看一下编译后的class文件或许能明白

  39. // 在编译的时候会把内部类编译成一个实现了ICallback的class

  40. // doStm(new ICallback() {

  41. // /**

  42. // * 现在这个方法是doStm结束后调用<br>

  43. // * 结束之后会主动把处理参数params传递过来

  44. // */

  45. // @Override

  46. // public void callback(Map<String, Object> params) {

  47. // System.out.println("单个线程也已经处理完毕了,返回参数a1=" + params.get("a1"));

  48. // }

  49. // });

  50. doStm((params)->{

  51. System.out.println("单个线程也已经处理完毕了,返回参数a1=" + params.get("a1"));

  52. });

  53. System.out.println("主线任务已经执行完了:"+Thread.currentThread().getId());

  54. }

  55. }


打印结果:

  1. 子线任务执行:11

  2. 主线任务已经执行完了:1

  3. 单个线程也已经处理完毕了,返回参数a1=这是我返回的参数字符串...

  4. Process finished with exit code 0


Future 

Futures是一个抽象的概念,它表示一个值,该值可能在某一点变得可用。一个Future要么获得 
计算完的结果,要么获得计算失败后的异常。Java在java.util.concurrent包中附带了Future接口,它使用Executor异步执行。例 
如下面的代码,每传递一个Runnable对象到ExecutorService.submit()方法就会得到一个回调的Future,你能使用它检测是否执行,这种方法可以是同步等待线处理结果 
完成。 

  1. package callback;

  2. import java.util.concurrent.Callable;

  3. import java.util.concurrent.ExecutionException;

  4. import java.util.concurrent.ExecutorService;

  5. import java.util.concurrent.Executors;

  6. import java.util.concurrent.Future;

  7. /**

  8. * Future

  9. * Futures是一个抽象的概念,它表示一个值,该值可能在某一点变得可用。一个Future要么获得

  10. 计算完的结果,要么获得计算失败后的异常。Java在java.util.concurrent包中附带了Future接口,

  11. 它使用Executor异步执行。例

  12. 如下面的代码,每传递一个Runnable对象到ExecutorService.submit()方法就会得到一个回调的Future,

  13. 你能使用它检测是否执行,这种方法可以是同步等待线处理结果

  14. 完成。

  15. */

  16. public class NettyTest {

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

  18. //实现一个Callable接口

  19. Callable<Netty> c = new Callable<NettyTest.Netty>() {

  20. @Override

  21. public Netty call() throws Exception {

  22. //这里是你的业务逻辑处理

  23. //让当前线程阻塞1秒看下效果

  24. Thread.sleep(1000);

  25. return new Netty("张三");

  26. }

  27. };

  28. ExecutorService es = Executors.newFixedThreadPool(2);

  29. //记得要用submit,执行Callable对象

  30. Future<Netty> fn = es.submit(c);

  31. //一定要调用这个方法,不然executorService.isTerminated()永远不为true

  32. es.shutdown();

  33. //无限循环等待任务处理完毕 如果已经处理完毕 isDone返回true

  34. while (!fn.isDone()) {

  35. try {

  36. //处理完毕后返回的结果

  37. Netty nt = fn.get();

  38. System.out.println(nt.name);

  39. } catch (InterruptedException e) {

  40. e.printStackTrace();

  41. } catch (ExecutionException e) {

  42. e.printStackTrace();

  43. }

  44. }

  45. }

  46. static class Netty {

  47. private String name;

  48. private Netty(String name) {

  49. this.name = name;

  50. }

  51. }

  52. }


打印结果:

  1. 张三

  2. Process finished with exit code 0


 


文章转载自那些年的代码,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论