【问题标题】:How to call an API with multithreading in Java? [duplicate]如何在 Java 中调用具有多线程的 API? [复制]
【发布时间】:2021-07-04 21:24:55
【问题描述】:

我正在尝试编写一个并行调用 API 的应用程序。虽然,由于某种原因,只要我调用 需要 多次调用的方法,它就不会阻塞父(主)......我已经在网上看到了大量的代码使用 ExecutorService 对象等等,但我的问题是我需要这个线程异步运行,这意味着我不能将调用分组到列表或循环中。

这是我得到的:

  // This is the method I call from the outside.
  public static String callAPI(String _from, String _to, String _text) {
    APIThread t = new APIThread (_from, _to, _text);
    return t.getResult();
  }

然后,在 APIThread 中:

public class APIThread implements Runnable {
    private Thread thread;
    private String data;

    public APIThread(...) {
       this.thread = new Thread(this);
       this.thread.start();
    }

    @Override
    public void run() {
       this.data = doSomeAPIWork();
    }

    public String getResult() {
       return this.data;
    }

    public String doSomeAPIWork() {
       // Use HttpUrlConnection to grab stuff and put it in StringBuilder - return as String
    }
}

这实际上就是我所拥有的 - 只是“伪代码”形式(因为 API 的细节无关紧要)。子线程启动,立即从方法中返回(也就是说APIThread类还没来得及设置数据实例。我感觉这真的很简单,我只是做错了。

编辑:澄清一下,我想要多线程的原因是因为 API 调用是零星的——这意味着我可以一次从程序中的不同位置获取十个左右,并且因为请求大约需要一秒钟或所以,我真的很希望有一个线程池等待执行作业,这意味着,如果我们遇到一个工作,就去做,然后如果我们遇到另一个,同时做那个。换句话说,我希望主线程看到一个 callAPI() 方法,对其进行处理,将其发送到一个线程,然后在其他地方继续(这意味着可能会找到另一个 callAPI() 调用)。

【问题讨论】:

  • 如果你分离一个线程,然后什么都不做,只等待结果(原始线程块),那么启动那个线程是没有意义的。异步工作的目标是释放原始线程以做其他事情。如果我误解了您的意图,请编辑您的问题以澄清。
  • @BasilBourque 添加。
  • 同样的问题。如何做到这一点:return t.getResult(); 无需坐在那里等待后台线程完成?在做庭院工作时,如果你站在软管旁边等着,让你的孩子装满一桶水有什么意义呢?您不妨自己装满桶,而不涉及您的孩子(隐喻的第二条线索)。
  • @BasilBourque 这就是我的问题所在。我不想要后台线程只是坐在那里完成。我想要一个线程来完成这项工作(这可能意味着我需要为 THIS 方法生成一个线程......)并从该线程返回结果......这有意义吗?
  • 但是就像我说的,我可能同时收到几个请求,这意味着,是的,虽然我可以自己拿起软管并装满桶,但我想把它典当如果我必须做其他事情,我的孩子(在我的代码示例中,如果有请求进来,我会把它丢给一个孩子,以便它可以处理它,以防我找到另一个请求)。

标签: java multithreading api http


【解决方案1】:

您可以使用接口来满足您的需求。例如,看看这个类:

public class ApiThread {
    private HashMap<String, String> params;
    private String url;
    private OnCompleteListener listener;

    public ApiThread(String url, HashMap<String, String> params) {
       this.url = url;
       this.params = params;
    }

    public void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // Use HttpUrlConnection to grab stuff and put it in result String
                if (ApiThread.this.listener != null) {
                    ApiThread.this.listener.OnComplete(result);
                }
            }
        }).start();
    }

    public ApiThread setListener(OnCompleteListener listener) {
        this.listener = listener;
        return this;
    }
    
    public interface OnCompleteListener {
        void OnComplete(String result);
    }
}

现在看看如何使用它:

HashMap<String, String> params = new HashMap<>();
params.put("username", "John Smith");
params.put("password", "1234567890");
new ApiThread("http://example.com/api/login", params)
    .setListener(new ApiThread.OnCompleteListener() {
        @Override
        public void OnComplete(String result) {
            // do whatever you want with result String, for example:
            System.out.println(result);
        }
    })
    .start();

基本上,它太简单了,但对接口的强大功能很有用。这样,您可以定义您的类在操作完成后应该做什么,而无需等待它完成,并且每当它完成任务(在本例中为 API 调用)时,它将运行传递的接口实现。

通过使用方法链(接口实例设置器),编码风格变得更加美观。

【讨论】:

  • 我认为您无法访问您拥有的 start() 方法中的 params HashMap...我需要能够访问它。
  • 当然它是可访问的,因为它是一个类字段成员,因此它通常可以在类的所有部分中访问,包括 start 方法。
  • 对,但我现在正在尝试它并没有列出它(也没有列出 APIThread 类的任何内部方法)。
  • 您可以使用ApiThread.this.params访问它
  • 顺便说一句,您使用的是哪个 IDE?我的意思是,你的 IDE 或文本编辑器没有列出它并不重要,因为它已经存在并且你可以使用它。这是内部 java 功能,可以安全使用。
猜你喜欢
  • 1970-01-01
  • 2011-03-30
  • 2019-06-15
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多