Hi all,
Do any of you have an experience using the Java API in a multithreaded
context? I'm trying to spread some processing across multiple threads to try
and speed things up, but am getting the exact opposite result. In this
instance, I'm trying to quickly delete a certain number of entries from a form,
and I'm finding that if I do it in a single thread, it deletes approximately 50
records/second. However, if I do it with two threads, the overall rate drops
to less than 25 records/second - not per thread, overall. That means that the
time that it takes to actually delete a single record is taking on average four
times longer when using 2 threads instead of 1. I get the same results whether
I use the same ARServerUser object in each thread or if I create new ones for
each thread.
Have any of you seen this or does anyone have any idea what might be going on
here?
I've copied the relevant source code below for your reference. Thanks for any
help.
Thanks,
Lyle Taylor
//=========================================================================
// This class is just used to encapsulate the list of entries to be deleted
// and synchronizes access to the list of entries shared among all the threads.
//=========================================================================
import java.util.List;
import java.util.Iterator;
import com.bmc.arsys.api.*;
public class EntriesToDelete {
String mForm;
List<Entry> mEntries;
int mReportFrequency;
int mReturnedCount = 0;
Iterator<Entry> mIter;
public EntriesToDelete(String inForm, List<Entry> inEntries, int
inReportFrequency) {
mForm = inForm;
mEntries = inEntries;
mReportFrequency = inReportFrequency;
mIter = mEntries.iterator();
}
public String Form() {
return mForm;
}
public Entry NextEntry() {
synchronized(this) {
++mReturnedCount;
if ( mReportFrequency != 0 && mReturnedCount %
mReportFrequency == 0 ) {
System.out.println("Deleted " + mReturnedCount + " of "
+ mEntries.size());
}
if ( mIter.hasNext() ) {
return mIter.next();
} else {
return null;
}
}
}
}
//=========================================================================
// This class does the actual work. An instance is created for each thread to
be run.
//=========================================================================
import com.bmc.arsys.api.*;
public class DeleteEntryWorker implements Runnable {
ARServerUser mSrv;
EntriesToDelete mEntries;
public DeleteEntryWorker(String inServer, String inUser, String
inPassword, int inPort, EntriesToDelete inEntries) {
mSrv = new ARServerUser(inUser, inPassword, null, inServer, inPort);
mEntries = inEntries;
}
public void run() {
Entry e;
while ( (e = mEntries.NextEntry()) != null ) {
try {
mSrv.deleteEntry(mEntries.Form(), e.getEntryId(), 0);
} catch (ARException ex) {}
}
}
}
//=========================================================================
// The following two methods perform the query to determine what to delete and
then spawns
// the threads that do the work. They belong to the application's class.
//=========================================================================
public static void CleanNotifierLogs(ARServerUser inServer) throws
ARException, InterruptedException {
String form = "NTE:Notifier Log";
int fields[] = {1};
OutputInteger nMatches = new OutputInteger();
// only 500 entries are being pulled back for testing
List<Entry> entries = inServer.getListEntryObjects(form, null, 0,
500, null, fields, false, nMatches);
if ( nMatches.intValue() > 0 ) {
DeleteEntries(inServer, form, entries, 2, 50);
}
}
public static void DeleteEntries(ARServerUser inServer, String inForm,
List<Entry> inEntries, int inNumThreads, int inReportFrequency) throws
ARException, InterruptedException {
EntriesToDelete entries = new EntriesToDelete(inForm, inEntries,
inReportFrequency);
// Two methods have been tried, just to see if there would be any
difference
// ExecutorService pool = Executors.newFixedThreadPool(inNumThreads);
//
// for (int i = 0; i < inNumThreads; ++i) {
// pool.execute(new DeleteEntryWorker(inServer.getServer(),
inServer.getUser(), inServer.getPassword(), inServer.getPort(), entries));
// }
// pool.shutdown();
Thread threads[] = new Thread[inNumThreads];
for (int i = 0; i < inNumThreads; ++i) {
threads[i] = Executors.defaultThreadFactory().newThread(new
DeleteEntryWorker(inServer.getServer(), inServer.getUser(),
inServer.getPassword(), inServer.getPort(), entries));
threads[i].start();
}
for (int i = 0; i < inNumThreads; ++i) {
threads[i].join();
}
}
NOTICE: This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any unauthorized
review, use, disclosure or distribution is prohibited. If you are not the
intended recipient, please contact the sender by reply email and destroy all
copies of the original message.
_______________________________________________________________________________
UNSUBSCRIBE or access ARSlist Archives at www.arslist.org
Platinum Sponsor:[email protected] ARSlist: "Where the Answers Are"