Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从URL列表中并发获取InputStreams?_Java_Multithreading_Api_Url_Concurrency - Fatal编程技术网

Java 如何从URL列表中并发获取InputStreams?

Java 如何从URL列表中并发获取InputStreams?,java,multithreading,api,url,concurrency,Java,Multithreading,Api,Url,Concurrency,目前,我正在尝试返回一个inputstream,该inputstream包含一个序列inputstreams列表,每个序列inputstreams通过API从它们自己的url生成。问题是,当按顺序完成时,API需要几秒钟来生成数据。因此,API在连接过程中会缩短几秒钟。api的结构如下所示: www.api.com?q=ENCODEDTEXT 我现在有这个代码来按顺序添加它们 public InputStream getMP3Data(List<String> synthText)

目前,我正在尝试返回一个inputstream,该inputstream包含一个序列inputstreams列表,每个序列inputstreams通过API从它们自己的url生成。问题是,当按顺序完成时,API需要几秒钟来生成数据。因此,API在连接过程中会缩短几秒钟。api的结构如下所示:

www.api.com?q=ENCODEDTEXT
我现在有这个代码来按顺序添加它们

public InputStream getMP3Data(List<String> synthText){
    InputStream complete = getMP3Data(synthText.remove(0));
    for(String part: synthText){
        complete = new java.io.SequenceInputStream(complete, getMP3Data(part));//Concatenate with new MP3 Data
    }
    return complete;
}
public InputStream getMP3Data(列表文本){
InputStream complete=getMP3Data(synthText.remove(0));
for(字符串部分:synthText){
complete=new java.io.SequenceInputStream(complete,getMP3Data(part));//连接新的MP3数据
}
返回完成;
}
getMP3Data(String)是通过自动编码URL并获取输入流来访问URL的方法。getMP3Data(List)的要点是使用完整的数据列表执行相同的操作。我面临的问题是如何通过多线程实现这一点。我想同时为列表中的每个项目调用getMP3Data(String)。我将如何做到这一点?我事先不知道名单的大小。任何帮助都将不胜感激

编辑:这就是我最终使用的。将上述代码的执行速度提高了900%以上。

    /**
 * Gets an InputStream to MP3Data for the returned information from a request
 * @param synthText List of Strings you want to be synthesized into MP3 data
 * @return Returns an input stream of all the MP3 data that is returned from Google
 * @throws IOException Throws exception if it cannot complete the request
 */
public InputStream getMP3Data(List<String> synthText) throws IOException{
    //Uses an executor service pool for concurrency
    ExecutorService pool = Executors.newFixedThreadPool(synthText.size());
    //Stores the Future (Data that will be returned in the future)
    Set<Future<InputStream>> set = new LinkedHashSet<Future<InputStream>>();
    //Iterates through the list
    for(String part: synthText){
        Callable<InputStream> callable = new MP3DataFetcher(part);//Creates Callable
        Future<InputStream> future = pool.submit(callable);//Runs the Callable
        set.add(future);//Adds the response that will be returned to a set.
    }
    List<InputStream> inputStreams = new ArrayList<InputStream>(set.size());
    for(Future<InputStream> future: set){
        inputStreams.add(future.get());//Gets the response that will be returned, returned.
    }
    return new SequenceInputStream(Collections.enumeration(inputStreams));//Sequences the stream
}


     /**
 * This class is a callable.
 * A callable is like a runnable except that it can return data and throw exceptions.
 * Useful when using futures. 
 * @author Skylion
 *
 */
private class MP3DataFetcher implements Callable<InputStream>{
    private String synthText;

    public MP3DataFetcher(String synthText){
        this.synthText = synthText;
    }

    public InputStream call() throws Exception{
        return getMP3Data(synthText);
    }
}
/**
*为请求返回的信息获取MP3Data的InputStream
*@param synthText要合成为MP3数据的字符串列表
*@return返回从Google返回的所有MP3数据的输入流
*@throws-IOException无法完成请求时抛出异常
*/
公共InputStream getMP3Data(List synthText)引发IOException{
//使用执行器服务池进行并发
ExecutorService池=Executors.newFixedThreadPool(synthText.size());
//存储将来(将来将返回的数据)
Set Set=newlinkedhashset();
//遍历列表
for(字符串部分:synthText){
Callable Callable=新的MP3DataFetcher(部分);//创建可调用的
Future=pool.submit(可调用);//运行可调用
set.add(future);//添加将返回到集合的响应。
}
List inputStreams=new ArrayList(set.size());
for(未来:集合){
inputStreams.add(future.get());//获取将返回的响应,返回。
}
返回新的SequenceInputStream(Collections.enumeration(inputStreams));//对流进行排序
}
/**
*这个类是可调用的。
*callable与runnable类似,只是它可以返回数据并引发异常。
*使用期货时很有用。
*@author Skylion
*
*/
私有类MP3DataFetcher实现可调用{
私有字符串文本;
公共MP3DataFetcher(字符串合成文本){
this.synthText=synthText;
}
公共InputStream调用()引发异常{
返回getMP3Data(synthText);
}
}
公共输入流getMP3Data(列表文本){
List threads=new ArrayList();
//为每个MP3源启动一个线程
for(字符串部分:synthText){
线程thr=新的GetMP3Stream(部分);
thr.start();
螺纹。添加(thr);
}
//在列表中收集打开的输入流
列表流=新的ArrayList();
for(GetMP3Stream thr:线程){
thr.join();
添加(thr.res);
}
//连接所有输入流
返回新的java.io.SequenceInputStream(streams);
}
类GetMP3Stream扩展了线程{
字符串url;
输入流;
GetMP3Stream(字符串url){
this.url=url;
}
公开募捐{
res=getMP3Data(url);
}
}

Google for ExecutorService您能更具体一点吗?Executor服务似乎非常适合处理并发事件,但我不认为它在这种情况下有多大用处。让它修改InputStreams列表不会引发concurrentModificationException吗?让我指出,顺序也很重要。只要不要修改输入流列表,使用.invokeAll(),这样您就可以按顺序完成任务。谢谢您的回复。然而,我最终还是使用了Callables。将我的基准代码的执行速度提高900%!!!
public InputStream getMP3Data(List<String> synthText){
  List<GetMP3Stream> threads=new ArrayList<GetMP3Stream>();
  // start a thread for each MP3 source
  for(String part: synthText){
    Thread thr=new GetMP3Stream(part);
    thr.start();
    threads.add(thr);
  }
  // collect opened input streams in a list
  List<InputStream> streams=new ArrayList<InputStream>();
  for(GetMP3Stream thr: threads){
    thr.join();
    streams.add(thr.res);
  }
  //Concatenate all input streams 
  return  new java.io.SequenceInputStream(streams);
}

class GetMP3Stream extends Thread {
 String url;
 InputStream res;
 GetMP3Stream (String url) {
   this.url=url;
 }
 public void run() {
   res=getMP3Data(url);
 }
}