Java native process timeout - java

At the moment I execute a native process using the following:
java.lang.Process process = Runtime.getRuntime().exec(command);
int returnCode = process.waitFor();
Suppose instead of waiting for the program to return I wish to terminate if a certain amount of time has elapsed. How do I do this?

All other responses are correct but it can be made more robust and efficient using FutureTask.
For example,
private static final ExecutorService THREAD_POOL
= Executors.newCachedThreadPool();
private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit)
throws InterruptedException, ExecutionException, TimeoutException
{
FutureTask<T> task = new FutureTask<T>(c);
THREAD_POOL.execute(task);
return task.get(timeout, timeUnit);
}
final java.lang.Process[] process = new Process[1];
try {
int returnCode = timedCall(new Callable<Integer>() {
public Integer call() throws Exception {
process[0] = Runtime.getRuntime().exec(command);
return process[0].waitFor();
}
}, timeout, TimeUnit.SECONDS);
} catch (TimeoutException e) {
process[0].destroy();
// Handle timeout here
}
If you do this repeatedly, the thread pool is more efficient because it caches the threads.

If you're using Java 8 or later (API 26 or later for Android) you could simply use the waitFor with timeout:
Process p = ...
if(!p.waitFor(1, TimeUnit.MINUTE)) {
//timeout - kill the process.
p.destroy(); // consider using destroyForcibly instead
}

This is how the Plexus CommandlineUtils does it:
Process p;
p = cl.execute();
...
if ( timeoutInSeconds <= 0 )
{
returnValue = p.waitFor();
}
else
{
long now = System.currentTimeMillis();
long timeoutInMillis = 1000L * timeoutInSeconds;
long finish = now + timeoutInMillis;
while ( isAlive( p ) && ( System.currentTimeMillis() < finish ) )
{
Thread.sleep( 10 );
}
if ( isAlive( p ) )
{
throw new InterruptedException( "Process timeout out after " + timeoutInSeconds + " seconds" );
}
returnValue = p.exitValue();
}
public static boolean isAlive( Process p ) {
try
{
p.exitValue();
return false;
} catch (IllegalThreadStateException e) {
return true;
}
}

What about the Groovy way
public void yourMethod() {
...
Process process = new ProcessBuilder(...).start();
//wait 5 secs or kill the process
waitForOrKill(process, TimeUnit.SECONDS.toMillis(5));
...
}
public static void waitForOrKill(Process self, long numberOfMillis) {
ProcessRunner runnable = new ProcessRunner(self);
Thread thread = new Thread(runnable);
thread.start();
runnable.waitForOrKill(numberOfMillis);
}
protected static class ProcessRunner implements Runnable {
Process process;
private boolean finished;
public ProcessRunner(Process process) {
this.process = process;
}
public void run() {
try {
process.waitFor();
} catch (InterruptedException e) {
// Ignore
}
synchronized (this) {
notifyAll();
finished = true;
}
}
public synchronized void waitForOrKill(long millis) {
if (!finished) {
try {
wait(millis);
} catch (InterruptedException e) {
// Ignore
}
if (!finished) {
process.destroy();
}
}
}
}

just modified a bit according to my requirement. time out is 10 seconds here. process is getting destroyed after 10 seconds if it is not exiting.
public static void main(String arg[]) {
try {
Process p = Runtime.getRuntime().exec("\"C:/Program Files/VanDyke Software/SecureCRT/SecureCRT.exe\"");
long now = System.currentTimeMillis();
long timeoutInMillis = 1000L * 10;
long finish = now + timeoutInMillis;
while ( isAlive( p ) ) {
Thread.sleep( 10 );
if ( System.currentTimeMillis() > finish ) {
p.destroy();
}
}
} catch (Exception err) {
err.printStackTrace();
}
}
public static boolean isAlive( Process p ) {
try {
p.exitValue();
return false;
} catch (IllegalThreadStateException e) {
return true;
}
}

You'd need a 2. thread that interrupts the thread that calls .waitFor();
Some non trivial synchronization will be needed to make it robust, but the basics are:
TimeoutThread:
Thread.sleep(timeout);
processThread.interrupt();
ProcessThread:
try {
proc.waitFor();
} catch (InterruptedException e) {
proc.destroy();
}

Related

Efficient Timeout for a blocking operation without synchronization

I'm trying to create a timeout for a blocking operation, a InputStream.read() in the specific case, using a timeout thread without synchronization.
This is needed to avoid that a blocking operation will last forever and its aim is to achieve the best performance.
This should be a typical use case:
try(InputStream input = request.getInputStream())
{
Utils.consumeWithTimeout(input, 60000, (buffer, n) ->
{
output.write(buffer, 0, n);
checksum.update(buffer, 0, n);
});
}
where
public static void consumeWithTimeout(InputStream in, long timeout, BiConsumer<byte[], Integer> consumer) throws IOException
{
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
try(TimedOp timedOp = new TimedOp(timeout, () -> closeQuietly(in)))
{
while(true)
{
timedOp.start();
int n = in.read(buf);
timedOp.pause();
if(n <= 0)
{
return;
}
consumer.accept(buf, n);
}
}
finally
{
closeQuietly(in);
}
}
and
public static class TimedOp implements AutoCloseable
{
private Thread th;
private volatile long last = 0;
private volatile boolean paused = true;
public TimedOp(long timeout, Runnable runnable)
{
th = new Thread(() ->
{
try
{
while(!th.isInterrupted())
{
long now = System.currentTimeMillis();
if(last + timeout > now)
{
Thread.sleep(last + timeout - now);
}
else if(paused)
{
Thread.sleep(timeout);
}
else
{
runnable.run();
return;
}
}
}
catch(InterruptedException e)
{
return;
}
});
}
public void start()
{
State state = th.getState();
if(state == State.TERMINATED)
{
throw new IllegalStateException("thread is terminated");
}
if(!paused)
{
throw new IllegalStateException("already running");
}
last = System.currentTimeMillis();
paused = false;
if(state == State.NEW)
{
th.start();
}
}
public void pause()
{
paused = true;
}
#Override
public void close()
{
th.interrupt();
try
{
th.join();
}
catch(InterruptedException e)
{
throw new RuntimeException(e);
}
}
}
do you see a problem or space for improvement?
what I tried
Suppose you need to care about 1GB data transfer, with a 8KB buffer.
can I use an ExecutorService for scheduling the read()?
No, I can't.
public static void consumeWithExecutor(InputStream in, long timeout, BiConsumer<byte[], Integer> consumer) throws IOException
{
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
ExecutorService executor = Executors.newSingleThreadExecutor();
try
{
while(true)
{
Future<Integer> future = executor.submit(() -> in.read(buf));
int n = future.get(timeout, TimeUnit.MILLISECONDS);
if(n <= 0)
{
return;
}
consumer.accept(buf, n);
}
}
catch(InterruptedException | ExecutionException | TimeoutException e)
{
// do nothing, handling in finally block
}
finally
{
closeQuietly(in);
executor.shutdownNow();
}
}
the overhead of spawning/reusing/restarting a thread for each single read is overkill.
Performance loss is unbearable.
can I use a Timer for scheduling the read()?
No, I shouldn't.
public static void consumeWithTimer(InputStream in, long timeout, BiConsumer<byte[], Integer> consumer) throws IOException
{
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
try
{
while(true)
{
Timer timer = new Timer();
TimerTask task = new TimerTask()
{
#Override
public void run()
{
closeQuietly(in);
}
};
timer.schedule(task, timeout);
int n = in.read(buf);
timer.cancel();
if(n <= 0)
{
return;
}
consumer.accept(buf, n);
}
}
finally
{
closeQuietly(in);
}
}
Timer and TimerTask are not reusable, a new instance should be created for each iteration.
Internally, Timer synchronizes on a queue of tasks, leading to unnecessary locking.
This result in a performance loss, a little thinner than using an ExecutorService, nevertheless it's not as efficient as my original implementation.

How to give message when Threadpool Executor is completed?

I am trying to give a pop up alert message when my ThreadpoolExecutor is finished executing. It is searching email addresses from websites, once it is done I want a alert message as "Completed". Here is my Thread :-
public class Constant
{
public static final int NUM_OF_THREAD = 60;
public static final int TIME_OUT = 10000;
}
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool
(Constant.NUM_OF_THREAD);
Here is my Searching Operation class :-
class SearchingOperation implements Runnable {
URL urldata;
int i;
Set<String> emailAddresses;
int level;
SearchingOperation(URL urldata, int i, Set<String> emailAddresses, int level) {
this.urldata = urldata;
this.i = i;
this.emailAddresses = emailAddresses;
this.level = level;
if (level != 1)
model.setValueAt(urldata.getProtocol() + "://" + urldata.getHost() + "/contacts", i, 3);
}
public void run() {
BufferedReader bufferreader1 = null;
InputStreamReader emailReader = null;
System.out.println(this.i + ":" + poolMainExecutor.getActiveCount() + ":" + level + ";" + urldata.toString());
try {
if (level < 1) {
String httpPatternString = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9#:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9#:%_\\+.~#?&//=]*)";
String httpString = "";
BufferedReader bufferreaderHTTP = null;
InputStreamReader httpReader = null;
try {
httpReader = new InputStreamReader(urldata.openStream());
bufferreaderHTTP = new BufferedReader(httpReader
);
StringBuilder rawhttp = new StringBuilder();
while ((httpString = bufferreaderHTTP.readLine()) != null) {
rawhttp.append(httpString);
}
if (rawhttp.toString().isEmpty()) {
return;
}
List<String> urls = getURL(rawhttp.toString());
for (String url : urls) {
String fullUrl = getMatchRegex(url, httpPatternString);
if (fullUrl.isEmpty()) {
if (!url.startsWith("/")) {
url = "/" + url;
}
String address = urldata.getProtocol() + "://" + urldata.getHost() + url;
fullUrl = getMatchRegex(address, httpPatternString);
}
if (!addressWorked.contains(fullUrl) && fullUrl.contains(urldata.getHost())) {
addressWorked.add(fullUrl);
sendToSearch(fullUrl);
}
}
} catch (Exception e) {
//System.out.println("652" + e.getMessage());
//e.printStackTrace();
return;
} finally {
try {
if (httpReader != null)
bufferreaderHTTP.close();
} catch (Exception e) {
// e.printStackTrace();
}
try {
if (httpReader != null)
httpReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
String someString = "";
emailReader = new InputStreamReader(urldata.openStream());
bufferreader1 = new BufferedReader(
emailReader);
StringBuilder emailRaw = new StringBuilder();
while ((someString = bufferreader1.readLine()) != null) {
if (someString.contains("#")) {
emailRaw.append(someString).append(";");
}
}
//Set<String> emailAddresses = new HashSet<String>();
String emailAddress;
//Pattern pattern = Pattern
//.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Pattern
pattern = Pattern
.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Matcher matchs = pattern.matcher(emailRaw);
while (matchs.find()) {
emailAddress = (emailRaw.substring(matchs.start(),
matchs.end()));
// //System.out.println(emailAddress);
if (!emailAddresses.contains(emailAddress)) {
emailAddresses.add(emailAddress);
// //System.out.println(emailAddress);
if (!foundItem.get(i)) {
table.setValueAt("Found", i, 4);
foundItem.set(i, true);
}
String emails = !emailAddresses.isEmpty() ? emailAddresses.toString() : "";
model.setValueAt(emails, i, 2);
model.setValueAt("", i, 3);
}
}
} catch (Exception e) {
//System.out.println("687" + e.getMessage());
} finally {
try {
if (bufferreader1 != null)
bufferreader1.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (emailReader != null)
emailReader.close();
} catch (Exception e) {
e.printStackTrace();
}
Thread.currentThread().interrupt();
return;
}
}
After this the final snippet :-
private void sendToSearch(String address) throws Throwable {
SearchingOperation operation = new SearchingOperation(new URL(address), i,
emailAddresses, level + 1);
//operation.run();
try {
final Future handler = poolMainExecutor.submit(operation);
try {
handler.get(Constant.TIME_OUT, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
handler.cancel(false);
}
} catch (Exception e) {
//System.out.println("Time out for:" + address);
} catch (Error error) {
//System.out.println("Time out for:" + address);
} finally {
}
}
Implement Callable<Void> instead of Runnable and wait for all the task to terminate by calling Future<Void>.get():
class SearchingOperation implements Callable<Void>
{
public Void call() throws Exception
{
//same code as in run()
}
}
//submit and wait until the task complete
Future<Void> future = poolMainExecutor.submit(new SearchingOperation()).get();
Use ThreadPoolExecutor.awaitTermination():
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
As in your code, you create your ThreadPoolExecutor first
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Constant.NUM_OF_THREAD);
Then, you need to add Tasks to it:
poolMainExecutor.execute(myTask);
poolMainExecutor.submit(myTask);
execute will return nothing, while submit will return a Future object. Tasks must implement Runnable or Callable. An object of SearchingOperation is a task for example. The thread pool will execute the tasks in parallel, but each task will be executed by one thread. That means to effectively use NUM_OF_THREAD Threads you need to add at least NUM_OF_THREAD Tasks.
(Optional) Once you got all jobs to work, shutdown your pool. This will prevent new tasks from being submitted. It won't affect running tasks.
poolMainExecutor.shutdown();
At the end, you need to wait for all Tasks to complete. The easiest way is by calling
poolMainExecutor.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
You should adjust the amount of time you want to wait for the tasks to finish before throwing an exception.
Now that the work is done, notify the user. A simple way is to call one of the Dialog presets from JOptionPane, like:
JOptionPane.showMessageDialog(null, "message", "title", JOptionPane.INFORMATION_MESSAGE);
It will popup a little window with title "title", the message "message", an "information" icon and a button to close it.
This code can be used., it will check whether the execution is completed in every 2.5 seconds.
do {
System.out.println("In Progress");
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (poolMainExecutor.getActiveCount() != 0);
System.out.println("Completed");

Tracking Executing Threads

I am trying to figure out how I can track all the threads that my application is spawning. Initially, I thought I had it figured out using a CyclicBarrier, however I am seeing threads executing after my await call.
Below is the working pseudo code:
public class ThreadTesterRunner {
public static void main(String[] args) throws InterruptedException {
final CyclicBarrier cb = new CyclicBarrier(1);
ThreadRunner tr = new ThreadRunner(cb);
Thread t = new Thread(tr, "Thread Runner");
t.start();
boolean process = true;
// wait until all threads process, then print reports
while (process){
if(tr.getIsFinished()){
System.out.println("Print metrics");
process = false;
}
Thread.sleep(1000);
}
}
}
class ThreadRunner implements Runnable {
static int timeOutTime = 2;
private ExecutorService executorService = Executors.newFixedThreadPool(10);
private final CyclicBarrier barrier;
private boolean isFinished=false;
public ThreadRunner(CyclicBarrier cb) {
this.barrier = cb;
}
public void run(){
try {
boolean stillLoop = true; int i = 0;
while (stillLoop){
int size;
Future<Integer> future = null;
try {
future = executorService.submit(new Reader()); // sleeps
size = future.get();
} catch (InterruptedException | ExecutionException ex) {
// handle Errs
}
if(i == 3){
stillLoop = false;
this.barrier.await();
this.isFinished=true;
}
//System.out.println("i = "+i+" Size is: "+size+"\r");
i++;
}
} catch (InterruptedException | BrokenBarrierException e1) {
e1.printStackTrace();
}
}
public boolean getIsFinished(){
return this.isFinished;
}
}
class Reader implements Callable {
private ExecutorService executorService = Executors.newFixedThreadPool(1);
#Override
public Object call() throws Exception {
System.out.println("Reading...");
Thread.sleep(2000);
executorService.submit(new Writer());
return 1000;
}
}
class Writer implements Callable {
#Override
public Void call() throws Exception {
Thread.sleep(4000);
System.out.println("Wrote");
return null;
}
}
Can anyone suggest a way to ONLY print "print metrics" after all threads have run?
It doesn't seem like you're doing anything to coordinate with your Reader and Writer threads, which are the ones you want to wait for. If you pass your synchronization barrier through to those threads so that they can register and signal when they are done, it works just fine.
Here's a version rewritten to do so, using a Phaser instead of a CyclicBarrier. Note that each Reader and Writer registers itself upon construction, and notifies the synchronization barrier when it is done executing:
public class ThreadTesterRunner {
public static void main(String[] args) throws InterruptedException {
final Phaser cb = new Phaser();
ThreadRunner tr = new ThreadRunner(cb);
Thread t = new Thread(tr, "Thread Runner");
t.start();
boolean process = true;
// wait until all threads process, then print reports
while (process){
if(tr.getIsFinished()){
System.out.println("Print metrics");
process = false;
}
//else {
// System.out.println("Waiting: registered=" + cb.getRegisteredParties() + ", arrived=" + cb.getArrivedParties() + ", unarrived=" + cb.getUnarrivedParties());
//}
Thread.sleep(1000);
}
}
}
class ThreadRunner implements Runnable {
static int timeOutTime = 2;
private ExecutorService executorService = Executors.newFixedThreadPool(10);
private final Phaser barrier;
private boolean isFinished=false;
public ThreadRunner(Phaser phaser) {
this.barrier = phaser;
}
public void run(){
try {
boolean stillLoop = true; int i = 0;
while (stillLoop){
int size;
Future<Integer> future = null;
try {
future = executorService.submit(new Reader(this.barrier)); // sleeps
size = future.get();
} catch (InterruptedException | ExecutionException ex) {
// handle Errs
}
if(i == 3){
stillLoop = false;
this.barrier.awaitAdvance(0);
this.isFinished=true;
}
//System.out.println("i = "+i+" Size is: "+size+"\r");
i++;
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
public boolean getIsFinished(){
return this.isFinished;
}
}
class Reader implements Callable {
private Phaser barrier;
private ExecutorService executorService = Executors.newFixedThreadPool(1);
public Reader(Phaser phase) {
phase.register();
this.barrier = phase;
}
#Override
public Object call() throws Exception {
System.out.println("Reading...");
Thread.sleep(2000);
executorService.submit(new Writer(this.barrier));
this.barrier.arrive();
return 1000;
}
}
class Writer implements Callable {
private Phaser barrier;
public Writer(Phaser phase) {
phase.register();
this.barrier = phase;
}
#Override
public Void call() throws Exception {
Thread.sleep(4000);
System.out.println("Wrote");
this.barrier.arrive();
return null;
}
}
From what I can see you aren't waiting for the Writer to finish in the Reader. Is that the problem you are seeing?
You are also accessing isFinished from more than one thread without synchronization (which however, merely may delay the termination of the loop in this situation).
I don't see CyclicBarrier doing anything.
Not sure what you are trying to do, but I'd think about how simpler I can make it. For example, can Reader and Writer be combined into one task? Then, waiting for them to finish would merely be:
executorService.invokeAll(tasks);
System.out.println("Print metrics");
where tasks is a collection of tasks (see also this javadoc)

How do we know threadPoolExecutor has finished execution

I have a parent thread that sends messages to MQ and it manages a ThreadPoolExecutor for worker threads which listen to MQ and writes message to output file. I manage a threadpool of size 5. So when I run my program, I have 5 files with messages. Everything works fine until here. I now need to merge these 5 files in my parent thread.
How do I know ThreadPoolExecutor finished processing so I can start merging files.
public class ParentThread {
private MessageSender messageSender;
private MessageReciever messageReciever;
private Queue jmsQueue;
private Queue jmsReplyQueue;
ExecutorService exec = Executors.newFixedThreadPool(5);
public void sendMessages() {
System.out.println("Sending");
File xmlFile = new File("c:/filename.txt");
List<String> lines = null;
try {
lines = FileUtils.readLines(xmlFile, null);
} catch (IOException e) {
e.printStackTrace();
}
for (String line : lines){
messageSender.sendMessage(line, this.jmsQueue, this.jmsReplyQueue);
}
int count = 0;
while (count < 5) {
messageSender.sendMessage("STOP", this.jmsQueue, this.jmsReplyQueue);
count++;
}
}
public void listenMessages() {
long finishDate = new Date().getTime();
for (int i = 0; i < 5; i++) {
Worker worker = new Worker(i, this.messageReciever, this.jmsReplyQueue);
exec.execute(worker);
}
exec.shutdown();
if(exec.isTerminated()){ //PROBLEM is HERE. Control Never gets here.
long currenttime = new Date().getTime() - finishDate;
System.out.println("time taken: "+currenttime);
mergeFiles();
}
}
}
This is my worker class
public class Worker implements Runnable {
private boolean stop = false;
private MessageReciever messageReciever;
private Queue jmsReplyQueue;
private int processId;
private int count = 0;
private String message;
private File outputFile;
private FileWriter outputFileWriter;
public Worker(int processId, MessageReciever messageReciever,
Queue jmsReplyQueue) {
this.processId = processId;
this.messageReciever = messageReciever;
this.jmsReplyQueue = jmsReplyQueue;
}
public void run() {
openOutputFile();
listenMessages();
}
private void listenMessages() {
while (!stop) {
String message = messageReciever.receiveMessage(null,this.jmsReplyQueue);
count++;
String s = "message: " + message + " Recieved by: "
+ processId + " Total recieved: " + count;
System.out.println(s);
writeOutputFile(s);
if (StringUtils.isNotEmpty(message) && message.equals("STOP")) {
stop = true;
}
}
}
private void openOutputFile() {
try {
outputFile = new File("C:/mahi/Test", "file." + processId);
outputFileWriter = new FileWriter(outputFile);
} catch (IOException e) {
System.out.println("Exception while opening file");
stop = true;
}
}
private void writeOutputFile(String message) {
try {
outputFileWriter.write(message);
outputFileWriter.flush();
} catch (IOException e) {
System.out.println("Exception while writing to file");
stop = true;
}
}
}
How will I know when the ThreadPool has finished processing so I can do my other clean up work?
Thanks
If you Worker class implements Callable instead of Runnable, then you'd be able to see when your threads complete by using a Future object to see if the Thread has returned some result (e.g. boolean which would tell you whether it has finished execution or not).
Take a look in section "8. Futures and Callables" # website below, it has exactly what you need imo:
http://www.vogella.com/articles/JavaConcurrency/article.html
Edit: So after all of the Futures indicate that their respective Callable's execution is complete, its safe to assume your executor has finished execution and can be shutdown/terminated manually.
Something like this:
exec.shutdown();
// waiting for executors to finish their jobs
while (!exec.awaitTermination(50, TimeUnit.MILLISECONDS));
// perform clean up work
You can use a thread for monitoring ThreadPoolExecutor like that
import java.util.concurrent.ThreadPoolExecutor;
public class MyMonitorThread implements Runnable {
private ThreadPoolExecutor executor;
private int seconds;
private boolean run=true;
public MyMonitorThread(ThreadPoolExecutor executor, int delay)
{
this.executor = executor;
this.seconds=delay;
}
public void shutdown(){
this.run=false;
}
#Override
public void run()
{
while(run){
System.out.println(
String.format("[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s",
this.executor.getPoolSize(),
this.executor.getCorePoolSize(),
this.executor.getActiveCount(),
this.executor.getCompletedTaskCount(),
this.executor.getTaskCount(),
this.executor.isShutdown(),
this.executor.isTerminated()));
try {
Thread.sleep(seconds*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And add
MyMonitorThread monitor = new MyMonitorThread(executorPool, 3);
Thread monitorThread = new Thread(monitor);
monitorThread.start();
to your class where ThreadPoolExecutor is located.
It will show your threadpoolexecutors states in every 3 seconds.

Thread Execution not complete in a loop

I need to insert 50000 of records to the Database using 10 threads as 5000 per thread.
Ex. thread 1 will insert 1-5000, thread 2 will insert 5001-10000 etc.
I have use the ExecutorService to do this.
Code
ExecutorService threadPool = Executors.newFixedThreadPool(10);
int i=0;
while(i<vVec.size())
{
if(i<vVec.size())
{
DBInsertDetail rrr = (DBInsertDetail)vVec.get(i);
TestThread t1 = new TestThread(rrr);
threadPool.execute(t1);
}
i++;
}
try {
threadPool.shutdown();
boolean bTermination = false;
while (true)
{
bTermination = threadPool.awaitTermination(15, TimeUnit.MINUTES);
if(!bTermination)
{
Log.debug("Awaiting completion of threads.");
}
else
{
Log.debug("Threads Completed."+iTermiVal);
break;
}
if(threadPool.isTerminated())
{
break;
}
}
} catch (Exception e) {}
TestThread class
public class TestThread implements Runnable
{
private volatile DBInsertDetail syncc;
public Thread1(DBInsertDetail syncc) {
this.syncc = syncc;
}
public void run() {
try
{ this.syncc.cardCreProcess(syncc.getIncre(),syncc.getStarterial(),syncc.getCurTblSeq());
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
DBInsertDetail class
public class DBInsertDetail {
public void cardCreProcess(int iNum,int iCurrSerl,int iCurTblSeq)
{
int iCardCountTest = 0;
try
{
synchronized(this)
{
for (int i = 0; i < iNum; i++)
{
iCurrSerl++;
iCurTblSeq++;
iCardCountTest++;
CmnDet stkDet = new CmnDet();
Data crdData = new Data();
String sNo = crdData.getNextNo(pro, prof, sBranch, iCurrSerl);
stkDet.setNo(sNo);
stkDet.setCod(""+iCurTblSeq);
if (!stkDet.saveToDataBase(con))
{
sErrorMsg +="Error Occured" + "\n";
}
}
}
}catch(Exception ex)
{
ex.printStackTrace();
}
finally{
//commit and return connection
}
}
}
Problem is this will not execute correctly for larger nos. If increase the records per thread 10000, process runs without any error but inserts only a part of batch. Any idea?
This is wrong, read the comment. :) Leaving it due to consistency of the thread
You sleep 1000ms in the thread. That is 1 second.
10000 inserts = 10000 seconds = 166 minutes.
You allow the thread pool 15 minutes to execute, then you shut it down.

Categories