Reputation: 91
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
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
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
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