我在哪里可以使用线程来改进这些方法?

时间:2015-09-29 02:49:22

标签: java arrays multithreading

好的,对于我在CSC330类中的项目,我应该使用线程快速找到大量数据集中查询的答案。数组中的每个项目都是用户,字符串是他们在由数字标识的网站上访问的网站的集合。

示例(数组是String users [])

用户[1] =“1 4 5 7”用户[2] =“1 2 7 17 10”用户[3] =“6”

查询是:

  • 有超过___个用户查看X
  • 有多少用户关注X
  • 是否有更多用户查看X而不是Y
  • 有多少用户查看了X ____次数
  • 有多少用户使用X而不是Y

此阵列中有大约一百万用户,我们必须在没有线程的情况下解决以下查询,而不是用于测试的较小规模版本的数据。我的所有工作。现在我需要切换到海量文本文件,我需要使用线程来提高速度。我想知道哪里有益,以及我如何实现这些线程。我将提供用于解决每个查询的代码。我想我可以使用多个线程同时遍历数组的各个部分,但我不知道如何执行它。

    public boolean query1(String num, String pageName){
    if(num == null){
        return false;
    }
    else
    {
        int userCount = 0;
        int pageNum = convert(pageName);
        System.out.println(pageNum);
        String pageNumString = Integer.toString(pageNum);
        System.out.println(pageNumString);
        for(int i = 0; i < users.length; i++ )
        {
            for(String entry : users[i].split(" "))
            {
                if(entry.equals(pageNumString))
                {
                    userCount++;
                    break;
                }   
            }
    }
    if(userCount > Integer.parseInt(num)){
        return false;
    }
    else{
        return true;
    }
    }
    }
public float query2(String pageName){
    int userCount = 0;
    int pageNum = convert(pageName);
    String pageNumString = Integer.toString(pageNum);
    for(int i = 0; i < users.length; i++ )
    {
        for(String entry : users[i].split(" "))
        {
            if(entry.equals(pageNumString))
            {
                userCount++;
                break;
            }   

        }
    }
    float percentage = (userCount*100.0f)/users.length;
    return percentage;  
}
public boolean query3(String pageName, String pageName2){
    int userCount1 = 0;
    int userCount2 = 0;
    String pageNumString = Integer.toString(convert(pageName));
    String pageNumString2 = Integer.toString(convert(pageName2));
    for(int i = 0; i < users.length; i++ )
    {
        for(String entry : users[i].split(" "))
        {
            if(entry.equals(pageNumString))
            {
                userCount1++;
                break;
            }   
        }
        for(String entry : users[i].split(" "))
        {
            if(entry.equals(pageNumString2))
            {
                userCount2++;
                break;
            }   
        }
    }
    return userCount1 > userCount2;

}
public int query4(String pageName, int numTimes){
    int userCount = 0;
    String pageNumString = Integer.toString(convert(pageName));
    for(int i = 0; i < users.length; i++ )//runs through each user
    {   int pageCount = 0;
        for(String entry : users[i].split(" "))// runs through each user's pages
        {
            if(entry.equals(pageNumString))
            {
                pageCount++;                // each time page is found page count increments 1
            }   
        }                                  // once done running through user's pages
        if(pageCount == numTimes){         // check if the number of pages is equal to the number given
            userCount++;                   // if so increment userCount
        }
    }
    return userCount;
}
public float query5(String pageName, String pageName2){
    int viewedMore = 0;
    int userCount1 = 0;
    int userCount2 = 0;
    String pageNumString = Integer.toString(convert(pageName));
    String pageNumString2 = Integer.toString(convert(pageName2));
    for(int i = 0; i < users.length; i++ )
    {
        for(String entry : users[i].split(" ")){
            userCount1 = 0;
            userCount2 = 0;
            if(entry.equals(pageNumString))
            {
                userCount1++;
                break;
            }   
        }
        for(String entry : users[i].split(" "))
        {
            if(entry.equals(pageNumString2))
            {
                userCount2++;
                break;
            }   
        }
        if(userCount1 > userCount2){
            viewedMore++;
        }
    }
    return viewedMore*100.0f/users.length;  
}

1 个答案:

答案 0 :(得分:1)

至少,在query3query5中,您可以为两个内部for循环中的每一个生成线程;没有理由他们必须按顺序运行。对于任何查询函数,您当然可以将数组拆分为多个部分。由于您的数据越来越大,这种方法很可能比使用线程迭代数据更快。

我建议提供线程连续的段(例如索引0到N-1; N到N + N-1等)。之前的StackOverflow answer提供了很好的理由,说明为什么这种方法最有效。一旦你得到了一些工作,你可以使用线程数来优化。

编辑以解决您在下面的评论

一种方法是实现strategy pattern,这样每个查询都可以在客户端上互换,其中executeQuery()调用是接口方法。想想让客户的电话看起来像

interface Query {
    boolean executeQuery();
}

// client code...
Client client = new Client(...);
client.setQuery(new Query3(String num, String pageNum));
client.query(); // calls query.executeQuery();

在具体的Query类中,您可以定义线程将执行的操作的各个行为。这是一个粗略的例子:

public Query3 implements Query { 
    Query3(String pageNum`, String pageNum2) {
        this.pageNum1=pageNum1;
        this.pageNum2=pageNum2;
    }

    boolean executeQuery() {
        for(int i = 0; i < users.length; i++ ) {
            SearchThread first = new SearchThread(pageNum1);
            SearchThread second = new SearchThread(pageNum2);
            first.run();
            second.run();
        }
        first.join();
        second.join();
        return first.userCount > second.userCount;
   }

SearchThread extends Thread {
    String pageNumString;
    int userCount;
    SearchThread(String pageNumString) {
        this.pageNumString=pageNumString;
    }
    public void run() {
        // do your search over this segment of the array, adding up userCounts
    }

这是另一个StackOverflow question,它描述了如何在单个阵列上运行多个线程,并使用一些样板代码。