简体   繁体   English

如何在Java中使用线程?

[英]how to use Thread in java?

i have code use googleseach API 我有代码使用googleseach API

I want to use Thread to improve speed of my program. 我想使用Thread来提高程序速度。 But i have a problem 但是我有一个问题

here is code 这是代码

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);       
    }
}

when i run it, it can run into run method but it don't excute make query methor and return null array. 当我运行它时,它可以运行到run方法中,但它不会执行make查询methor并返回null数组。

when i do't use Thread it can nomal . 当我不使用线程时,它可以正常运行。

Can you give me the reason why ? 你能给我原因吗? or give a sulution 或给出解决方案

Thanks 谢谢

One of the main problems is that you didn't wait for the asynchronous computation to complete. 主要问题之一是您没有等待异步计算完成。 You can wait by using Thread.join() , but it'll be even better if you use a Future<V> , such as a FutureTask<V> instead. 您可以使用Thread.join()等待,但是如果您使用Future<V> (例如FutureTask<V> Thread.join()会更好。

A Future represents the result of an asynchronous computation. Future表示异步计算的结果。 Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. 提供了一些方法来检查计算是否完成,等待其完成以及检索计算结果。 The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. 只有在计算完成后才可以使用get方法检索结果,必要时将其阻塞,直到准备就绪为止。

API links API链接

Tutorials and lessons 教程和课程

See also 也可以看看

  • Effective Java 2nd Edition 有效的Java第二版
    • Item 68: Prefer executors and tasks to threads 项目68:将执行程序和任务优先于线程
    • Item 69: Prefer concurrency utilities to wait and notify 项目69:建议并发实用程序waitnotify

Your problem is simply that you're not waiting for the thread to perform its job, so you can't get the result. 您的问题很简单,就是您不等待线程执行其工作,因此无法获得结果。 This can be fixed by simply doing 这可以通过简单地解决

test.join(); 

before getting the result. 在得到结果之前。 Of course, that way the code isn't any faster than if you were doing everything in the main thread. 当然,这种方式的代码并没有比在主线程中完成所有操作更快。 Threads don't make things magically faster. 线程不会神奇地使事情变得更快。 You'll only get a benefit if you do multiple queries in parallel. 只有并行执行多个查询,您才能受益。

It is making call to your makeQuery method but getting connection timeout exception as appended below. 它正在对您的makeQuery方法进行调用,但获取连接超时异常,如下所示。

Call test.join(); 调用test.join(); before printing the content to avoid abrupt ending of program. 在打印内容之前,请避免程序的突然结束。 Handle this connection exception as per your need. 根据您的需要处理此连接异常。

I would also recommend instead of using join() as an alternate you can use timed waiting mechanism like wait(timeout) or CountDounLatch.await(timeout) etc 我还建议不要使用join()作为替代方法,而可以使用定时等待机制,如wait(timeout)或CountDounLatch.await(timeout)等

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)

I believe you need to wait for the thread to complete before you can read the results. 我相信您需要等待线程完成才能读取结果。 Use Thread.join() for that purpose. 为此使用Thread.join()。

  1. You don't wait for the thread to finish its calculation before getting the result, therefore you won't get the result. 您无需等待线程完成其计算即可获得结果,因此您将不会获得结果。
  2. Doing the same work in a single new thread will not be any faster than doing it in the main thread. 在一个新线程中完成相同的工作不会比在主线程中完成任何工作更快。
  3. Doing multiple requests in multiple threads may be faster than doing them serially in a single thread. 多个线程中执行多个请求可能比在单个线程中依次执行多个请求要快。
  4. You should avoid handling threads directly when it's much simpler to use a thread pool (via an ExecutorService implementations as returned by one of the helper methods in Executors ) which gives the same benefits and keeps you from doing all the manual synchronizaton and waiting, which is very error prone. 你应该避免直接处理线程时,它更易于使用线程池(通过ExecutorService实现通过在辅助方法之一返回的Executors ),这也是同样的好处,并让你做完所有的手动synchronizaton和等待,这是容易出错。

when you call test.start(); 当您调用test.start(); the new thread test is started, while the original main thread continues .. you then immediately continue processing on the main thread, calling test.getResultGoogleArrayList() which at that point (immediately) is still null as the thread test is most likely still processing the method makeQuery . 新的线程test开始,而原始main线程继续..然后,您立即继续在main线程上进行处理,调用test.getResultGoogleArrayList() ,由于此时线程test很可能仍在处理中,因此该方法(立即)仍为null方法makeQuery

what you are trying to do is not really geared towards multi-threading and you are not likely to see any performance improvements simply by executing something on its own thread. 您尝试做的事情并不是真正针对多线程的,并且仅通过在自己的线程上执行某些操作就不可能看到任何性能改进。

multi-threading is only useful if you have more than one task that can be processed concurrently, whereas what you are doing fits the linear or synchronous paradigm. 仅当您具有多个可以同时处理的任务,而您正在执行的任务适合线性或同步范例时,多线程才有用。

Before you start trying 'to use threads to improve the speed of your program' you should understand exactly what threading is. 在开始尝试“使用线程来提高程序速度”之前,您应该确切了解什么是线程。 It is not some magic tool that just makes things faster. 这并不是使速度更快的魔术工具。 It allows you to perform multiple tasks 'simultaneously', depending on your hardware etc. If you have a single core processor it won't be simultaneous but execution can switch from one thread to the other whenever one thread has to wait for something to happen (eg user interaction etc.). 它使您可以“同时”执行多个任务,具体取决于您的硬件等。如果您只有一个核心处理器,它不会是同时执行的,但是只要一个线程必须等待某件事发生,执行就可以从一个线程切换到另一个线程(例如,用户交互等)。 There are other reasons for threads to switch execution and it depends on a lot of factors, which you don't really need to know, just appreciate that you can't take anything for granted when it comes to threading (don't assume something will happen at a specific time unless you specifically tell it to do so). 线程还有其他原因来切换执行,这取决于很多因素,您实际上并不需要知道这些因素,只是要意识到,在线程化方面您不能认为任何事情都是理所当然的(不要假设某些事情)除非您明确要求,否则它将在特定时间发生)。

In your example above you have 2 threads, the main thread and the GoogleSearchEngine thread. 在上面的示例中,您有2个线程,即主线程和GoogleSearchEngine线程。 In the main thread you create the second thread and tell it to start. 在主线程中,创建第二个线程并告诉它启动。 But as I said they can both run simultaneously so execution in the main thread will continue onto the next line to get the results, but the other thread may not even have started, or at least not got round to doing anything worthwhile, which is why you are getting null. 但是正如我所说的,它们都可以同时运行,因此主线程中的执行将继续到下一行以获得结果,但是另一个线程可能甚至没有启动,或者至少没有做任何有价值的事情,这就是为什么您将获得空值。

In this case there is absolutely no reason to use multiple threads. 在这种情况下,绝对没有理由使用多个线程。 Your program does one task then ends, so it might as well do it all in one thread. 您的程序执行一个任务然后结束,因此它最好在一个线程中完成所有任务。

The sun java tutorial on concurrency. Sun Java并发教程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM