0x2B
0x2B

Reputation: 91

Multi-threading and queuing

I kinda got the hang of threads but now I'm confused. I don't quite understand queues at all. I created a thread pool executor which initializes a set amount of threads and each of those threads input a username(string) on a website to check if its available or not. So basically I was thinking I should queue this? like queue.add(username) and queue.remove(username) or queue.take.. So I was wondering how to do queues with thread pools and which type. SynchronousQueue, BlockingQueue, or is there a better alternative? Sorry I really dont understand queuing. Ignore the bad code. Just want it to work before I make it net

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()){ }

this is class 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.");
    }

Upvotes: 1

Views: 318

Answers (3)

markspace
markspace

Reputation: 11030

Oh, you're concerned about returning a result. Per your comment:

I updated with code. When I do this it goes way too fast. even though I put thread to sleep for 3.5 secs. I dont think it actually sleeps. So I thought I should add queue to prevent loss of data or w/e

Well you should have said that in your question. You could use a queue, but Java actually has it's own mechanism for returning data. You should at least try that first.

To return a result, use the Callable interface instead of Thread/Runnable. Callable works just like Runnable except you can return a value. When you submit a Callable to an executor service, you get a Future back. Just save it and then call get() to get your result. That's it, all the hard work of making queues or synchronization is already done for you.

The only thing left is checking for InterruptedException in nearly every imaginable place. ;)

/**
 *
 * @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";
   }

}

Upvotes: 1

Azee
Azee

Reputation: 63

I actually dont understand why you are synchronizing on filterUsers. How does the thread entering that synchronized code block modify filterUsers? Assuming that filterUsers is some type of a List implementation (that does not seem to be the case here) that you need to synchronize on so that threads block when putting or taking elements in it, you could get rid of that synchronized code block with a BlockingQueue. The BlockingQueue would block all threads doing put() when size() reaches capacity until elements are removed with a take(). So unless your synchronized code block is on a List that needs blocking, a blocking queue is not going to be of help.

Upvotes: 1

Amir Raminfar
Amir Raminfar

Reputation: 34149

The ideas of queues are producers and consumers. Producers put items on the queue, which the consumer threads (usually multiple threads) pick up the items and process.

SynchronousQueue - is a queue that must have a corresponding call to take() before put() returns.

BlockingQueue - is an interface. SynchronousQueue is an implementation of this BlockingQueue

So right about now you are probably very confused. I doubt you need SynchQueue. I recommend first you should read the javadoc for BlockingQueue.

Personally, you will probably want to use ArrayBlockingQueue. You should provide a capacity. Otherwise, if the producer puts more items on the queue then you will run out of memory.

Upvotes: 1

Related Questions