目前,我正在尝试返回一个输入流,该输入流由一系列顺序输入流组成,每个输入流都是通过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;
}
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);
}
}
答案 0 :(得分:1)
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);
}
}