Solved

How to implement multi-threaded polling

Posted on 2014-02-28
6
269 Views
Last Modified: 2014-03-02
I have a small single threaded app that continually polls a remote server for new items. If any items are found, it processes a batch of 50 items (max).  After the items are processed it sends a request to the remote server, telling it to mark those 50 items as processed (if successful). Finally it closes the connection and sleeps for a few minutes. Then grabs the next batch of items. In psuedo-code it looks something like this:

    while (!canceled) {

       SomeConnection conn = getConnectionToRemoteServer();
       List<Foo> items = conn.getNewItems(50);

       List<Foo> processed = new ArrayList<Foo>();
       for (Foo foo: items) {
           successful = processItem(foo);

           if (successful) {
              processed.add(foo);
           }
           else {
              doSomethingElse();
           }

           if (canceled) {
               break;
           }
       }  

       conn.removeItems(processed);              
       
       //... close connection
      Thread.sleep(someInterval);
    }

This all works fine. However, I would like to speed up the process by splitting up the work across multiple threads. Ideally, I'd like to submit the 50 tasks for processing, and do something when all tasks are finished. (Then begin again, when the next batch is received). But also support the ability to cancel the current batch at any time and shutdown the app if needed.

I'm looking for general ideas on how to accomplish this. I've been reading about ExcecutorService and CompletionService, and it seems promising, but I'm not clear on how to structure the overall process.  

Again, I'm just looking for high level advice on fitting the various pieces together rather than actual code.  Any thoughts or suggestions would be greatly appreciated!
0
Comment
Question by:_agx_
  • 3
  • 3
6 Comments
 
LVL 26

Accepted Solution

by:
dpearson earned 500 total points
ID: 39896628
I think you can do this with an ExecutorService.

The basic structure would be:

a) Create the executor (you choose how many threads will actually do the work here)
b) Create a list of tasks
c) Each task is a Callable instance which means they have a call() method that does all the work for one request - submit request to remote app, wait for result.
d) When you submit them to the executor (via invokeAll) you'll get back a list of Future objects.  Keep those futures.
e) Now your master app can do whatever it wants (including just calling awaitTermination() on the executor if you just want to wait for the work to be done)
f) If you want to abort the requests, go through the futures and call cancel() on them, which will trigger an InterruptedException inside the tasks - which will break them out of where they are waiting for a response from the remote host and let you abort.

I hope that helps get you started in the right direction,

Doug
0
 
LVL 52

Author Comment

by:_agx_
ID: 39896644
Thanks, that helps solidify some of what I've been reading in the javadocs.

One part I'm unclear on.. since the polling would be an ongoing process is the ExecutorService intended to be created once for each batch of tasks ... or would it be created once and reused many times?  I was thinking the latter, but I'm not sure.  If it could be done either way, what are the pros/cons?

Also, any advantage to ExecutorService over CompletionService?
0
 
LVL 26

Assisted Solution

by:dpearson
dpearson earned 500 total points
ID: 39896779
An executorService is a pool of threads.  So usually there's no advantage to disposing of all of the threads and creating new ones between batches of tasks.  It's better to just re-use them, just so you don't have the overhead of extra thread creation.

I've not personally used CompletionServices (and I've used dozens of executor services) but I believe the benefit is when you are more interested in getting access to the results from the executor as soon as they become available.  So where you want to have the Callable return an object to you and you want to handle those objects.

I find that's rarely the pattern I use (generally the task is updating some other state) and it sounds like you would most likely be doing that too with the "processItem()" sort of model.  But if you instead had more of a "getMeTheResult()" model then a completion service should make it easier to check for which tasks are "done now" and so where those results are available when each task could take different amounts of time.

A good example of this would be if you had a series of queues and you wanted to pass results from one to the next queue, with each queue implemented as a thread pool.  A completion service would potentially make that more efficient.  I think you can do the same with an executor service, it's just you'd need to write more of the code to check for what's done yourself.

Anyway I'm thinking an executor is probably enough for you here.

Doug
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 52

Author Comment

by:_agx_
ID: 39897644
> getting access to the results from the executor as soon as they become available.  

Hm.. that aspect could be applicable to my process, ie Run the pre-processing steps which *can* be cancelled:

             runStep1();
             runStep2();

Then pass off the result to another process to do the notifications and db inserts: But I don't know that it entirely fits the multi queues model. That might add a layer of complexity I don't think is needed. I'll have to give it some more thought.

> d) When you submit them to the executor (via invokeAll) you'll get back a list of Future objects.  Keep those futures.

With regards to the returned Futures list, doesn't invokeAll block until the tasks are completed? In which case, I couldn't loop through the FutureTasks's and invoke cancel(..) on each one.
0
 
LVL 26

Expert Comment

by:dpearson
ID: 39897768
With regards to the returned Futures list, doesn't invokeAll block until the tasks are completed? In which case, I couldn't loop through the FutureTasks's and invoke cancel(..) on each one.

Yep - sorry I mispoke there.  You don't want to use invokeAll in your case.  You just want to walk the list of tasks and submit() them - which will give you the Future, which you keep :)

Doug
0
 
LVL 52

Author Comment

by:_agx_
ID: 39897997
Gotcha.  Thanks for your clear responses. Exactly the kind of sounding board I was looking for :)  

Cheers
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to implement Singleton Design Pattern in Java.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now