如何在java中使用Thread?

时间:2010-05-10 11:41:20

标签: java multithreading

我的代码使用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时,它可以正常。

你能告诉我原因吗?或者给予贬低

谢谢

7 个答案:

答案 0 :(得分:4)

主要问题之一是您没有等待异步计算完成。您可以使用Thread.join()等待,但如果您使用Future<V>(例如FutureTask<V>),情况会更好。

  

Future表示异步计算的结果。提供方法以检查计算是否完成,等待其完成,以及检索计算结果。只有在计算完成时才能使用方法get检索结果,必要时阻塞直到准备就绪。

API链接

教程和课程

另见

  • Effective Java 2nd Edition
    • 第68项:首选执行程序和任务到线程
    • 第69项:首选并发工具为waitnotify

答案 1 :(得分:2)

您的问题只是您没有等待线程执行其工作,因此您无法获得结果。只需执行

即可解决此问题
test.join(); 

获得结果之前。当然,这样代码并不比你在主线程中做所有事情都快。线程不会让事情神奇地变得更快。如果您并行执行多个查询,您将获得收益。

答案 2 :(得分:0)

我相信您需要等待线程完成才能阅读结果。 为此目的使用Thread.join()。

答案 3 :(得分:0)

  1. 在获得结果之前,您不会等待线程完成计算,因此您将无法获得结果。
  2. 在一个新主题中执行相同的工作比在主线程中执行相同的工作更快。
  3. 多个线程中执行多个请求可能比在单个线程中连续执行这些请求更快。
  4. 当使用线程池(通过ExecutorService中的一个辅助方法返回的Executors实现)更简单时,您应该避免直接处理线程,这会带来同样的好处并让您保持从做所有手动同步和等待,这是非常容易出错。

答案 4 :(得分:0)

当你调用test.start();时,新的线程test被启动,而原来的main线程继续...然后你立即继续处理main线程,调用{由于线程test.getResultGoogleArrayList()很可能仍处理方法null,因此(立即)仍然test {1}}。

你想要做的并不是真正面向多线程,你不可能仅仅通过在自己的线程上执行某些东西来看到任何性能改进。

多线程仅在您有多个可以同时处理的任务时才有用,而您正在做的事情符合线性或同步范例。

答案 5 :(得分:0)

在开始尝试“使用线程来提高程序的速度”之前,您应该准确理解线程是什么。它不是一个让事情变得更快的神奇工具。它允许您同时执行多个任务,具体取决于您的硬件等。如果您有一个单核处理器,它将不会同时执行,但只要一个线程必须等待某些事情发生,执行就可以从一个线程切换到另一个线程(例如用户交互等)。线程切换执行还有其他原因,这取决于很多因素,你真的不需要知道,只是感谢你在线程时不能把任何事情视为理所当然(不要假设某事)将在特定时间发生,除非您明确告知它这样做。)

在上面的示例中,您有2个主题,主线程和GoogleSearchEngine主题。在主线程中,您创建第二个线程并告诉它开始。但正如我所说他们可以同时运行所以主线程中的执行将继续到下一行来获得结果,但是另一个线程可能甚至没有启动,或者至少没有完成任何有价值的事情,这就是为什么你变得空了。

在这种情况下,绝对没有理由使用多个线程。你的程序完成一项任务然后结束,所以它也可以在一个线程中完成所有任务。

The sun java tutorial on concurrency.

答案 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)