我的代码使用googleseach API
我想使用Thread来提高程序的速度。但我有一个问题
这是代码
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import com.yahoo.search.WebSearchResult;
/**
* Simple Search using Google ajax Web Services
*
* @author Daniel Jones Copyright 2006 Daniel Jones Licensed under BSD open
* source license http://www.opensource.org/licenses/bsd-license.php
*/
public class GoogleSearchEngine extends Thread {
private String queryString;
private int maxResult;
private ArrayList<String> resultGoogleArrayList = null;
public ArrayList<String> getResultGoogleArrayList() {
return resultGoogleArrayList;
}
public void setResultGoogleArrayList(ArrayList<String> resultGoogleArrayList) {
this.resultGoogleArrayList = resultGoogleArrayList;
}
public String getQueryString() {
return queryString;
}
public void setQueryString(String queryString) {
this.queryString = queryString;
}
public int getMaxResult() {
return maxResult;
}
public void setMaxResult(int maxResult) {
this.maxResult = maxResult;
}
// Put your website here
public final static String HTTP_REFERER = "http://www.example.com/";
public static ArrayList<String> makeQuery(String query, int maxResult) {
ArrayList<String> finalArray = new ArrayList<String>();
ArrayList<String> returnArray = new ArrayList<String>();
try {
query = URLEncoder.encode(query, "UTF-8");
int i = 0;
String line = "";
StringBuilder builder = new StringBuilder();
while (true) {
// Call GoogleAjaxAPI to submit the query
URL url = new URL("http://ajax.googleapis.com/ajax/services/search/web?start=" + i + "&rsz=large&v=1.0&q=" + query);
URLConnection connection = url.openConnection();
if (connection == null) {
break;
}
// Value i to stop while or Max result
if (i >= maxResult) {
break;
}
connection.addRequestProperty("Referer", HTTP_REFERER);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));
while ((line = reader.readLine()) != null) {
builder.append(line);
}
String response = builder.toString();
JSONObject json = new JSONObject(response);
JSONArray ja = json.getJSONObject("responseData").getJSONArray("results");
for (int j = 0; j < ja.length(); j++) {
try {
JSONObject k = ja.getJSONObject(j);
// Break string into 2 parts: URL and Title by <br>
returnArray.add(k.getString("url") + "<br>" + k.getString("titleNoFormatting"));
}
catch (Exception e) {
e.printStackTrace();
}
}
i += 8;
}
// Remove objects that is over the max number result required
if (returnArray.size() > maxResult) {
for (int k=0; k<maxResult; k++){
finalArray.add(returnArray.get(k));
}
}
else
return returnArray;
return finalArray;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void run() {
// TODO Auto-generated method stub
//super.run();
this.resultGoogleArrayList = GoogleSearchEngine.makeQuery(queryString, maxResult);
System.out.println("Code run here ");
}
public static void main(String[] args)
{
Thread test = new GoogleSearchEngine();
((GoogleSearchEngine) test).setQueryString("data ");
((GoogleSearchEngine) test).setMaxResult(10);
test.start();
ArrayList<String> returnGoogleArrayList = null;
returnGoogleArrayList = ((GoogleSearchEngine) test).getResultGoogleArrayList();
System.out.print("contents of al:" + returnGoogleArrayList);
}
}
当我运行它时,它可以运行run方法但它不会执行make query methor并返回null数组。
当我不使用Thread时,它可以正常。
你能告诉我原因吗?或者给予贬低谢谢
答案 0 :(得分:4)
主要问题之一是您没有等待异步计算完成。您可以使用Thread.join()
等待,但如果您使用Future<V>
(例如FutureTask<V>
),情况会更好。
Future
表示异步计算的结果。提供方法以检查计算是否完成,等待其完成,以及检索计算结果。只有在计算完成时才能使用方法get检索结果,必要时阻塞直到准备就绪。
java.util.concurrent
(包含许多高级并发实用程序)
interface Future<V>
(表示异步计算的结果)
interface RunnableFuture<V>
(Future
Runnable
)
class FutureTask<V>
(包装Callable
或Runnable
对象的实现)interface Executor
(“通常使用而不是显式创建线程”)class Executors
(提供工厂和实用程序方法)wait
和notify
答案 1 :(得分:2)
您的问题只是您没有等待线程执行其工作,因此您无法获得结果。只需执行
即可解决此问题test.join();
获得结果之前。当然,这样代码并不比你在主线程中做所有事情都快。线程不会让事情神奇地变得更快。如果您并行执行多个查询,您将获得收益。
答案 2 :(得分:0)
我相信您需要等待线程完成才能阅读结果。 为此目的使用Thread.join()。
答案 3 :(得分:0)
ExecutorService
中的一个辅助方法返回的Executors
实现)更简单时,您应该避免直接处理线程,这会带来同样的好处并让您保持从做所有手动同步和等待,这是非常容易出错。答案 4 :(得分:0)
当你调用test.start();
时,新的线程test
被启动,而原来的main
线程继续...然后你立即继续处理main
线程,调用{由于线程test.getResultGoogleArrayList()
很可能仍处理方法null
,因此(立即)仍然test
{1}}。
你想要做的并不是真正面向多线程,你不可能仅仅通过在自己的线程上执行某些东西来看到任何性能改进。
多线程仅在您有多个可以同时处理的任务时才有用,而您正在做的事情符合线性或同步范例。
答案 5 :(得分:0)
在开始尝试“使用线程来提高程序的速度”之前,您应该准确理解线程是什么。它不是一个让事情变得更快的神奇工具。它允许您同时执行多个任务,具体取决于您的硬件等。如果您有一个单核处理器,它将不会同时执行,但只要一个线程必须等待某些事情发生,执行就可以从一个线程切换到另一个线程(例如用户交互等)。线程切换执行还有其他原因,这取决于很多因素,你真的不需要知道,只是感谢你在线程时不能把任何事情视为理所当然(不要假设某事)将在特定时间发生,除非您明确告知它这样做。)
在上面的示例中,您有2个主题,主线程和GoogleSearchEngine主题。在主线程中,您创建第二个线程并告诉它开始。但正如我所说他们可以同时运行所以主线程中的执行将继续到下一行来获得结果,但是另一个线程可能甚至没有启动,或者至少没有完成任何有价值的事情,这就是为什么你变得空了。
在这种情况下,绝对没有理由使用多个线程。你的程序完成一项任务然后结束,所以它也可以在一个线程中完成所有任务。
答案 6 :(得分:0)
它正在调用你的makeQuery方法,但是获得了连接超时异常,如下所示。
调用test.join();在打印内容之前,以避免程序突然结束。根据需要处理此连接异常。
我还建议您不要使用join()作为替代,而是可以使用等待等待机制,如wait(超时)或CountDounLatch.await(超时)等
java.net.ConnectException: Connection timed out: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:529)
....
....
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:570)
at at co.uk.mak.GoogleSearchEngine.makeQuery(GoogleSearchEngine.java:81)
at co.uk.mak.GoogleSearchEngine.run(GoogleSearchEngine.java:124)