多线程和排队

时间:2015-05-23 18:42:54

标签: java multithreading queue threadpool

我有点线程,但现在我很困惑。我根本不太了解队列。我创建了一个线程池执行器,它初始化一定数量的线程,每个线程在网站上输入一个用户名(字符串)来检查它是否可用。所以基本上我以为我应该排队呢?像queue.add(用户名)和queue.remove(用户名)或queue.take ..所以我想知道如何使用线程池和类型进行队列。 SynchronousQueue,BlockingQueue,还是有更好的选择?对不起,我真的不明白排队。忽略不良代码。只是希望它在我做网之前工作

FilterUsers FU = new FilterUsers();
HtmlThread[] threads = new HtmlThread[users.length];
ExecutorService executor = Executors.newFixedThreadPool(threadNo);
for (int i = 0; i < users.length; i++) {
    Runnable worker = new HtmlThread(" "+i, FU, users[i]);
    executor.execute(worker);
}    
executor.shutdown();
while (!executor.isTerminated()){ }

这是HtmlThread类

class HtmlThread extends Thread {
    private Thread t;
    private String threadName;
    FilterUsers filterUsers;
    String users;

    public HtmlThread(String tName, FilterUsers filterusers, String user) {
        this.threadName = tName;
        this.filterUsers = filterusers;
        this.users = user;
    }

    public void run() {
        synchronized (filterUsers) {
            try {
                HtmlPage page = webClient.getPage("https://website.com/account/edit");

                try {
                    final HtmlForm form = page.getFirstByXPath("//form[@class='adjacent bordered']");
                    HtmlTextInput user = form.getInputByName("username");
                    HtmlSubmitInput b = form.getInputByValue("Submit");
                    user.setValueAttribute(users);

                    HtmlPage page2;
                    page2 = b.click();

                   String html = page2.getWebResponse().getContentAsString();
                    if (page2 != null) {
                        if (!html.contains("that username is taken")) {
                            Filter.validUsers.appendText(users + "\n");
                        }
                    }
                } finally {
                    page.cleanUp();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            System.out.println("Thread " + threadName + " Sleeping.");

            Thread.sleep(3500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Thread " + threadName + " exiting.");
    }

3 个答案:

答案 0 :(得分:1)

队列的想法是生产者和消费者。生产者将项目放在队列中,消费者线程(通常是多个线程)接收项目和进程。

SynchronousQueue - 是一个队列,在take()返回之前必须对put()进行相应的调用。

BlockingQueue - 是一个界面。 SynchronousQueue是此BlockingQueue

的实现

现在你可能很困惑。我怀疑你需要SynchQueue。我建议您首先阅读BlockingQueue的javadoc

就个人而言,您可能希望使用ArrayBlockingQueue。你应该提供一个容量。否则,如果生产者在队列中放入更多项目,那么您将耗尽内存。

答案 1 :(得分:1)

我实际上不明白为什么你在filterUsers上进行同步。进入该同步代码块的线程如何修改filterUsers?假设filterUsers是某种类型的List实现(这里似乎不是这种情况),你需要进行同步,以便线程在放入或获取元素时阻塞,你可以摆脱同步代码块BlockingQueue的。当size()达到容量时,BlockingQueue会阻塞所有执行put()的线程,直到使用take()删除元素。 因此,除非您的同步代码块位于需要阻塞的List上,否则阻塞队列将无济于事。

答案 2 :(得分:1)

哦,你担心返回结果。根据你的评论:

  

我用代码更新了。当我这样做时,它太快了。即使   我让线程睡了3.5秒。我不认为它实际上是在睡觉。   所以我认为我应该添加队列以防止数据丢失或w / e

你应该在你的问题中说过。您可以使用队列,但Java实际上拥有自己的返回数据机制。你至少应该先尝试一下。

要返回结果,请使用Callable接口而不是Thread / Runnable。 Callable的工作方式与Runnable类似,但您可以返回一个值。当您将Callable提交给执行程序服务时,您将获得Future。只需保存即可,然后致电get()以获取结果。就是这样,制作队列或同步的所有艰苦工作已经为你完成了。

唯一剩下的就是在几乎所有可以想象的地方检查InterruptedException。 ;)

/**
 *
 * @author Brenden Towey
 */
public class FutureExample
{

   public static void main( String[] args )
   {
      ExecutorService exe = Executors.newFixedThreadPool(3);
      List<Future<String>> results = new ArrayList<>();
      for( int i = 0; i < 5; i++ )
         results.add( exe.submit( new HtmlTask() ) );
      try {
         for( Future<String> future : results )
             System.out.println( future.get() );
      } catch( InterruptedException x ) {
         // bail
      } catch( ExecutionException ex ) {
         Logger.getLogger( FutureExample.class.getName() ).
                 log( Level.SEVERE, null, ex );
         // and bail
      }
      exe.shutdown();
      boolean shutdown = false;
      try {
         shutdown = exe.awaitTermination(10 , TimeUnit.SECONDS );
      } catch( InterruptedException ex ) {
         // bail
      }
      if( !shutdown ) {
         exe.shutdownNow();
         try {
            exe.awaitTermination( 30, TimeUnit.SECONDS );
         } catch( InterruptedException ex ) {
            // just exit
         }
      }
   }
}

class HtmlTask implements Callable<String> {

   @Override
   public String call()
           throws Exception
   {
      // pretend to search a website and return some result
      return "200 OK";
   }

}