Android Thread is not timing out on wait/notify method - java

The timeout on b.wait(1000) instruction is not executing after 1 second.
I will appreciate some help on how to execute the timeout on the wait() method.
protected void onCreate(Bundle savedInstanceState) {
ThreadB b = new ThreadB();
b.start();
synchronized (b) {
try {
long start = System.currentTimeMillis();
Log.i(TAG, "Before Wait has started "+start);
b.wait(1000);
long finish = System.currentTimeMillis();
Log.i(TAG, "After Wait has finished "+finish);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
}
class ThreadB extends Thread {
#Override
public void run() {
synchronized (this) {
long start = System.currentTimeMillis();
Log.i(TAG, "*** Thread Start "+start);
Random ran = new Random();
for (int i = 0; i < 1E7; i++) {
Math.sin(ran.nextDouble());
}
long finish = System.currentTimeMillis();
Log.i(TAG, "*** Thread Finish "+finish);
notify();
}
}
}

Your program has a "race" to acquire the lock on the ThreadB object. If the main thread wins the race, the timeout logic works. If the new thread wins, the main thread has to wait for the new thread to finish so that it can grab the lock, and after that then it will call Object.wait and sleep for 1 second.
One quick fix is to make sure that the main thread has the lock before the new thread starts:
ThreadB b = new ThreadB();
synchronized (b) {
b.start();
try {
long start = System.currentTimeMillis();
....
}
}
A better solution is to start using the higher level concepts in the java.util.concurrent library. Instead of creating a new thread, send a task to be computed by a thread pool:
ExecutorService threadPool = Executors.newFixedThreadPool(1);
Future<?> submit = threadPool.submit(() -> {
// ThreadB computation logic
});
and then specify a timeout to wait for its results:
try {
submit.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
// handle timeout, interruption, exceptions
}
Note that on Android, it's not a great idea make the main thread block or wait, even if it's for only 1 second.

Related

Use semaphore to stop thread in timer from execution

I have the following java code, that uses the ScheduledExecuterService. Basically, there are two important calls made in this method: 1. the integrationMonitor.Processor(...) and 2. the runIntegrationSynching() methods.
The scheduler will make sure that these methods execute according to the time interval. Recently however, I've had the problem where processing of these two methods are very long. If the user then sets the timer interval to too low, the next processing cycle will start, even before the previous one finished.
Someone here suggested I use semaphores to do the synchronization, and I did - it works for one of my test cases, but not the other one.
I am using a semaphore to prevent a new schedule cycle to start, if a previous one is still busy. How can I know when a thread finished so that I can release the semaphore?
Here is the code:
static Semaphore semaphore = new Semaphore(1);
final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
try {
semaphore.acquire();
catch(InterruptedException e1) {}
runIntegrationSynching();
try {
semaphore.release();
} catch(InterruptedException e1) {}
Thread thread = new Thread(){
public void run(){
IntegrationMonitor intgrationMonitor = new IntegrationMonitor();
try {
semaphore.acquire();
} catch(InterruptedException e1) {}
intgrationMonitor.Processing(configXML, rcHost, alarmMonitorMap, blocker);
try {
semaphore.release();
} catch(InterruptedException e1) {}
if(intgrationMonitor != null){
intgrationMonitor = null;
}
}
};
LOGGER.info("Attempting to start the thread for RC " + rcHost + ". Thread ID:" + thread.getId());
thread.start();
}
},2,2,TimeUnit.MINUTES);

Measuring execution time over multiple threads

I want to measure the full execution time (so when ALL threads are done).
The trick with System.currentimeMillis won't work here, because when the main-method ends, my own created threads will still be running because they take longer time to process than the main-method.
How Can I do this?
I'll give an example.
public class Main {
public static void main(String[] args) {
long start = System.currentTimeMillis();
new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
long end = System.currentTimeMillis();
System.out.println(end - start); // Won't work because my new Thread will still be running here.
}
}
You can use an ExecutorService:
long startTime = System.nanoTime();
ExecutorService executorService = Executors.myPool();
for(conditions)
executorService.submit(new myThread());
Then don't forget to shutdown():
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
executorService.shutdown();
And wait:
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
executorService.awaitTermination(1, TimeUnit.HOUR); // however long you need
Then calculate:
long totalTime = System.nanoTime() - startTime;
System.out.printf("The total time everything took was %.3f ms %n", totalTime/1e6);
You should consider using thread Joins before measuring the end time. That will ensure that the main thread exit only when all other threads exit.
package threadsync;
public class MeasureRunningTime {
public static void main(String[] args) {
long start = System.currentTimeMillis();
Thread th = new Thread(){
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
};
th.start();
try {
th.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("The thread took:" + (end - start) + "ms");
}
}
Output in this case should be:
The thread took:5003ms

Issue in Future.cancel() method

I have a below runnable task which is run by using ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1)); This ensures that there will be only one waiting task in the queue.
protected void waitAndSweep(final String symbol) {
try {
runnable = new Runnable() {
#Override
public void run() {
try {
// long sweepTime = symbolInfo.getSweepTime(symbol);
// long timeSinceLastSweep = System.currentTimeMillis() - lastSliceSentTime;
boolean sliceDone = Quant.equals(wave.getCommitedQuantity() % getSliceQuantity(),0);
if(sliceDone){
long timeSinceLastSliceQtySent = lastSliceSentTime == 0 ? getInterval() : System.currentTimeMillis() - lastSliceSentTime;
long waitTime = timeSinceLastSliceQtySent >= getInterval() ? 0 : getInterval() - timeSinceLastSliceQtySent;
logTradeEvent("waitAndSweep", symbol, "waittime: " + waitTime);
if (waitTime > 0){
Thread.sleep(waitTime);
}
}
callSweep(symbol);
} catch(InterruptedException ie){
ie.printStackTrace();
}
catch (Exception e) {
logEvent(StrategyEntry.ERROR, "waitAndSweep", symbol,
"Exception caught...", e);
}
}
};
self = threadPoolExecutor.submit(runnable);
}catch(RejectedExecutionException re){
/* this exception will be thrown when wait and sweep is called more than twice.
* threadPoolExecutor can have one running task and one waiting task.
* */
System.out.print(re);
}catch (Exception e) {
logEvent(StrategyEntry.ERROR, "waitAndSweep", symbol,
"Exception caught...", e);
}
}
Consider the caller A :
private void callerA(){
waitandsweep();
waitandsweep();}
this craetes two task one will be running and another waiting in the queue.
Consider the callerB:
private void callerB(){
self.cancel(true);
waitandsweep();}
Expecting callerB to cancel all the tasks invoked by A.
Actually it is not happening.. task invoked by caller B is getting rejected because already one task is waiting in the queue. Can you please tell why this behaviour happens?
edit 1 : How to cancel running task of executor?
The problem is, that Future.cancel(boolean) doesn't remove the task from the queue. The Task will not be executed, once it will be pulled by the Executor but until then its still in the queue
try to use threadPoolExecutor.purge(); right after cancel(); it will try to remove the canceled tasks
cancelling a running Task is not that easy, you could try following:
call cancel(true); it will set Thread.interrupted() to true. Now in your Task check on some steps that value and so you can decide to skip next steps of your task

Java - Get thread state

I am using ThreadPoolExecutor to run the threads.
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> future = executorService.submit(new MyRunnable());
Based on some conditions, I need to terminate the long running thread and start the same thread instance again(for some cleanup operations).
Since I have a future object of the thread, I can easily check if it is still running.
future.isDone()
If it is running, I can send a interrupt signal by using
future.cancel(true);
In the MyRunnable class, the interrupt signal is handled. But this condition is checked at the beginning of the loop.
The problem is future.isDone() returns true as soon as interrupt signal is sent. But I need to wait till the thread instance is really completed.
Is there any way to check if the thread is really running/completed?
The Apidoc also mentions that future.isDone() returns true if future.cancel() was called, i.e. it does not always tell you if the task has finished.
To check if the task is finished, you need acces to the Runnable and then you can check if the task has completed or wait for it to complete.
Compare the code below with the output shown beneath it, I think that will give you an idea of your options:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Q21227864 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> future = executorService.submit(new MyRunnable());
sleep(100L);
future.cancel(true);
System.out.println("Future done: " + future.isDone());
sleep(100L);
future.cancel(true);
System.out.println("Future done: " + future.isDone());
sleep(500L);
System.out.println("Future done: " + future.isDone());
System.out.println("---");
MyRunnable mr = new MyRunnable();
future = executorService.submit(mr);
sleep(100L);
future.cancel(true);
System.out.println("Runnable done: " + mr.isDone());
sleep(100L);
System.out.println("Runnable done: " + mr.isDone());
mr.waitForCleanup();
System.out.println("Runnable done: " + mr.isDone());
executorService.shutdownNow();
}
public static void sleep(long timeMs) {
try { Thread.sleep(timeMs); } catch (Exception ignored) {}
}
static class MyRunnable implements Runnable {
final CountDownLatch completed = new CountDownLatch(1);
public void run() {
try {
System.out.println("Sleeping loop");
Thread.sleep(1000L);
System.out.println("Sleeping loop done");
} catch (Exception e) {
System.out.println("Stopped loop: " + e);
}
try {
System.out.println("Sleeping cleanup");
Thread.sleep(300L);
System.out.println("Sleeping cleanup done");
} catch (Exception e) {
System.out.println("Stopped cleanup: " + e);
}
completed.countDown();
}
public boolean isDone() {
return (completed.getCount() == 0);
}
public void waitForCleanup() {
try { completed.await(); } catch (Exception ignored) {}
}
}
}
Output:
Sleeping loop
Future done: true
Stopped loop: java.lang.InterruptedException: sleep interrupted
Sleeping cleanup
Future done: true
Sleeping cleanup done
Future done: true
---
Sleeping loop
Runnable done: false
Stopped loop: java.lang.InterruptedException: sleep interrupted
Sleeping cleanup
Runnable done: false
Sleeping cleanup done
Runnable done: true
I don't think future.isDone() returns true as soon as interrupt signal is sent. All ThreadPoolExecutor tasks are executed via FutureTask.run() method
public class FutureTask<V> implements RunnableFuture<V> {
...
public boolean isDone() {
return state != NEW;
}
public void run() {
...
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call(); <-- this invokes your code
ran = true;
} catch (Throwable ex) {
result = null; <-- if you threw InterruptedException
ran = false;
setException(ex); <-- state changes here
}
if (ran)
set(result); <-- if your code simply returns then state changes here
}
...

Thread.join() equivalent in executor [duplicate]

This question already has answers here:
ExecutorService, how to wait for all tasks to finish
(16 answers)
Closed 2 years ago.
I have a newbie question. I have this code:
public class Main
{
public static void main(String[] args) throws InterruptedException
{
// TODO Auto-generated method stub
IntHolder aHolder=new IntHolder();
aHolder.Number=0;
IncrementorThread A= new IncrementorThread(1, aHolder);
IncrementorThread B= new IncrementorThread(2, aHolder);
IncrementorThread C= new IncrementorThread(3, aHolder);
A.start();
B.start();
C.start();
A.join();
B.join();
C.join();
System.out.println("All threads completed...");
}
}
Which will wait for all threads to complete. If I use Executors like this:
public class Main
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
IntHolder aHolder=new IntHolder();
aHolder.number=0;
IncrementalRunable A= new IncrementalRunable(1, aHolder);
IncrementalRunable B= new IncrementalRunable(2, aHolder);
IncrementalRunable C= new IncrementalRunable(3, aHolder);
ExecutorService exec = Executors.newFixedThreadPool(3);
exec.execute(A);
exec.execute(B);
exec.execute(C);
//Don't know what to do here
System.out.println("All threads completed...");
}
}
How can I suspend the main thread to wait for all the threads in the executor to finish, i.e the "All threads completed..." should be printed after the all the threads have done their work?
You shouldn't use executor like this if you want to wait for tasks to finish.
What if you don't want/can't shutdown your thread pool executor?
This is a more recommended way:
ExecutorService exec = Executors.newFixedThreadPool(3);
Collection<Future<?>> tasks = new LinkedList<Future<?>>();
Future<T> future = exec.submit(A);
tasks.add(future);
future = exec.submit(B);
tasks.add(future);
future = exec.submit(C);
tasks.add(future);
// wait for tasks completion
for (Future<?> currTask : tasks) {
try {
currTask.get();
} catch (Throwable thrown) {
Logger.error(thrown, "Error while waiting for thread completion");
}
}
executor.shutdown();
while (!executor.awaitTermination(24L, TimeUnit.HOURS)) {
System.out.println("Not yet. Still waiting for termination");
}
Use shutdown() + awaitTermination() combination.
EDIT:
Based on the comment of #Lital
List<Callable<Object>> calls = new ArrayList<Callable<Object>>();
calls.add(Executors.callable(new IncrementalRunable(1, aHolder)));
calls.add(Executors.callable(new IncrementalRunable(2, aHolder)));
calls.add(Executors.callable(new IncrementalRunable(3, aHolder)));
List<Future<Object>> futures = executor.invokeAll(calls);
NOTE:
invokeAll() will not return until all the tasks are completed (either by failing or completing successful execution).
We can use below code to join the thread.
executor.execute(new YouThread());
try{
executor.shutdown();
while (!executor.awaitTermination(24L, TimeUnit.HOURS)) {
System.out.println("Not yet. Still waiting for termination");
}
}catch(InterruptedException e){
e.printStackTrace();
}
Try working with thread pool this way.
executor.shutdown();
executor.awaitTermination(MAX_PRIORITY, TimeUnit.HOURS);
exec.shutdown();
// Wait until all threads are finish
exec.awaitTermination();

Categories