I am using the Ebay API to place a bid on an item. If there is some kind of network error so that the API call does not return, I want to retry the call immediately afterwards. It seems so simple but I've been going round in circles all day. I'm not really experienced with threading. Is this how it's supposed to work or am I totally wrong?
Here is the Callable class:
public class PlaceOfferThread implements Callable<Boolean> {
private PlaceOfferCall call;
public Boolean isComplete;
public PlaceOfferThread (PlaceOfferCall p) {
call = p;
}
#Override
public Boolean call() throws Exception {
try {
call.placeOffer();
return true;
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
return false;
}
}
And here is the caller
int timeout = 10;
int maxRetries = 5;
int retries = 0;
ExecutorService executor = Executors.newSingleThreadExecutor();
PlaceOfferThread thread = new PlaceOfferThread(call);
boolean flag = false;
while (!flag && retries++ < maxRetries) {
Future<Boolean> future = null;
try {
future = executor.submit(thread);
flag = future.get(timeout, TimeUnit.SECONDS);
future.cancel(true);
}
catch(TimeoutException ex) {
// no response from Ebay, potential network issues
// resubmit the call to Ebay with the same invocation id
future.cancel(true);
}
catch (Exception threadException) {
// any other exception indicates that we got a response from Ebay
// it just wasn't the response we wanted
throw new Exception(threadException.getMessage());
}
}
executor.shutdown(); // TODO
If there is some kind of network error so that the API call does not return, I want to retry the call immediately afterwards.
I'm not 100% sure how your application is working right now but here are some thoughts:
When you call future.cancel(true) you most likely will not be stopping the current transaction. Unless you are using NIO calls, IO methods are not interruptible. Interrupting a thread just sets a flag on the thread and caused those few methods that throw InterruptedException (like sleep, wait, join) to do so. You'll have to watch the Thread.currentThread().isInterrupted() method to be able to see the interrupt otherwise.
I think the right thing to do is to set the connection and IO timeouts of the underlying http-client object and have it throw or exit with an error if there are problems. Trying to kill it from another thread is going to be much more difficult.
In looking at your code I'm not sure why you are using threads at all. Maybe you are doing other processing but it might be better to make the call directly. Then you can tune the HttpClient's IO timeouts and handle them appropriately.
Related
I'm working on a program that processing a large stream of items and sends each result to a REST server. That server has a rate limit of 2000 requests per hour, so the program must pause a while between processing two items. Items failed to process should be presented to the user afterwards.
It all worked fine, until I discovered that shutdownNow() isn't working when the program is closed. The UI closes but the executor keeps working. Underneath a brief summary of the code.
ExecutorService exec = Executors.newSingleThreadExecutor();
SomeProcessor p = new SomeProcessor();
void process() {
exec.submit(() -> {
Stream<SomeObject> s = ...
List<SomeObject> failed = p.process(s);
// show failed in UI
};
}
void exit() {
exec.shutdownNow();
}
And the SomeProcessor class:
List<SomeObject> process(Stream<SomeObject> s) {
List<SomeObject> failed = s
.sequential()
.filter(o -> !ignore(o)) // ignore irrelevant items
.peek(o -> pause()) // make sure not to exceed server's rate limit
.filter(o -> !process(o)) // keep items failed to process
.collect(Collectors.asList());
return failed;
}
void pause() {
try {
TimeUnit.MILLISECONDS.sleep(...);
} catch (final InterruptedException e) {
Thread.interrupted();
}
}
boolean process(SomeObject o) {
if (Thread.interrupted()) // make task interruptible
// *** but then what? ***
try {
// process o and send result to server
return true;
} catch (SomeException e) {
return false;
}
}
I guess that shutdownNow() wasn't working because the task isn't interruptible. So I'm trying to make the task interruptible, but I don't know what it should look like. Any ideas?
And a bonus question too. The pause() method does what it should do. Still I'd rather use something like ScheduledThreadPoolExecutor.scheduleAtFixedRate(.), but then processing a stream of tasks. Does anything exist like that?
Thanks for any help!
Look at your pause method:
void pause() {
try {
TimeUnit.MILLISECONDS.sleep(...);
} catch (final InterruptedException e) {
Thread.interrupted();
}
}
You are already detecting interruption at this point but react on it by setting the interrupt state of the thread again, or at least trying to do so, as Thread.interrupted() should be Thread.currentThread().interrupt() to achieve this, which would be fine, if you do not want to support interruption, but here it is counter-productive. It will cause your next sleep call to throw an InterruptedException immediately, which you handle the same way, and so on. As a result, you’re not only proceeding with the processing of the remaining elements, you’re doing it without the sleeping between the elements.
When you change the method to
void pause() {
try {
TimeUnit.MILLISECONDS.sleep(...);
} catch (final InterruptedException e) {
throw new IllegalStateException("interrupted");
}
}
interruption will terminate your stream operation with the IllegalStateException. For clarity, you may define your own exception type (extending RuntimeException) for this scenario, distinguishable from all other exception types.
I am calling some service that returns a response thru some callback function.
I used thread to call this service so that it is running in its own process.
The thread is called in my Main thread.
My question is how can I optimize my busy while loop in calling this service.
Sometimes the service fails and it is okay to just continue to retry looping in until a good response is received.
public class ProcessResponse extends Thread
boolean isOK = false;
public void responseReturned(Response response){
//more code
if(response.OK){
//process result
isOK = true;
}
}
public void run(){
while(true){
// call service
Thread.sleep(1000);
if(isOK)
break;
}
}
}
UPDATE 2:
My next line of thinking is just to use latch
public class ProcessResponse extends Thread
boolean isOK = false;
CountDownLatch latch = new CountDownLatch(1);
public void responseReturned(Response response){
//more code
if(response.OK){
//process result
isOK = true;
}
latch.countDown();
}
public void run(){
while(!isOK){
// call service
try {
latch.await();
} catch (InterruptedException e) {
//handle interruption
}
latch = new CountDownLatch(1);
}
}
}
There is no sleep command but I am not sure if reinitializing the latch is a good approach. The service sometimes takes time to return.
Note..I haven't tried this code yet.. I just type it in so I am not sure if this will work.
There are lot of options that are fortunately available in JAVA 5 which you can use:
1) Cyclic Barrier:
Create a cyclic barrier of 2 and as the responseReturned will be called through main thread, you can simply put cyclic barrier await function to implement this. It has advantage that you can reuse the same barrier again and again without need to reinialize it.
2) CountDown Latch
Create a countdown latch of 1 and as soon as the responseReturned call the countdown function of latch, the await function in run will allow it to move ahead. It has a disadvantage that you have to reinitialize latch in case you want to reuse it.
3) ExecutorService
You can also use ExecutorService and can call future object get method to wait till proper response is returned.
4) Semaphore You can also use aquire before calling the service and release it in responseReturned. In run you can again call aquire post call to wait till response is returned.
All of them will allow you to implement the functionality with almost similar efficiency.
Hope that helps.
Future interface may be used for these kind of interactions along with ExecutorService I guees. Once you submit a request ,you can set the timeout for the callback etc.
Future<String> futureTask = executorService.submit(callable);
String result = null;
try {
result = futureTask.get(500, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
I am writing a program that does some batch processing. The batch elements can be processed independently of each other and we want to minimize overall processing time. So, instead of looping through each element in the batch one at a time, I am using an ExecutorService and submitting Callable objects to it:
public void process(Batch batch)
{
ExecutorService execService = Executors.newCachedThreadPool();
CopyOnWriteArrayList<Future<BatchElementStatus>> futures = new CopyOnWriteArrayList<Future<BatchElementStatus>>();
for (BatchElement element : batch.getElement())
{
Future<MtaMigrationStatus> future = execService.submit(new ElementProcessor(batch.getID(),
element));
futures.add(future);
}
boolean done = false;
while (!done)
{
for (Future<BatchElementStatus> future : futures)
{
try
{
if (future.isDone())
{
futures.remove(future);
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
if (futures.size() == 0)
{
done = true;
}
}
}
}
We want to be able to allow the batch processing to be cancelled. Because I'm not using a loop, I can't just check at the top each loop if a cancel flag has been set.
We are using a JMS topic to which both the BatchProcessor and ElementProcessor will be listening to inform them the batch has been cancelled.
There are a number of steps in the ElementProcess call() after which some of them the processing can be safely stopped but there's a point of no return. The class has this basic design:
public class ElementProcessor implements Callable, MessageListener
{
private cancelled = false;
public void onMessage(Message msg)
{
// get message object
cancelled = true;
}
public BatchElementStatus call()
{
String status = SUCCESS;
if (!cancelled)
{
doSomehingOne();
}
else
{
doRollback();
status = CANCELLED;
}
if (!cancelled)
{
doSomehingTwo();
}
else
{
doRollback();
status = CANCELLED;
}
if (!cancelled)
{
doSomehingThree();
}
else
{
doRollback();
status = CANCELLED;
}
if (!cancelled)
{
doSomehingFour();
}
else
{
doRollback();
status = CANCELLED;
}
// After this point, we cannot cancel or pause the processing
doSomehingFive();
doSomehingSix();
return new BatchElementStatus("SUCCESS");
}
}
I'm wondering if there's a better way to check if the batch/element has been cancelled other than wrapping method calls/blocks of code in the call method in the if(!cancelled) statements.
Any suggestions?
I don't think you can do much better than what you are currently doing, but here is an alternative:
public BatchElementStatus call() {
return callMethod(1);
}
private callMethod(int methodCounter) {
if (cancelled) {
doRollback();
return new BatchElementStatus("FAIL");
}
switch (methodCounter) {
case 1 : doSomethingOne(); break;
case 2 : doSomethingTwo(); break;
...
case 5 : doSomethingFive();
doSomethingSix();
return new BatchElementStatus("SUCCESS");
}
return callMethod(methodCounter + 1);
}
Also, you want to make cancelled volatile, since onMessage will be called from another thread. But you probably don't want to use onMessage and cancelled anyway (see below).
Other minor points: 1) CopyOnWriteArrayList<Future<BatchElementStatus>> futures should just be an ArrayList. Using a concurrent collection mislead us into thinking that futures is on many thread. 2) while (!done) should be replaced by while (!futures.isEmpty()) and done removed. 3) You probably should just call future.cancel(true) instead of "messaging" cancellation. You would then have to check if (Thread.interrupted()) instead of if (cancelled). If you want to kill all futures then just call execService.shutdownNow(); your tasks have to handle interrupts for this to work.
EDIT:
instead of your while(!done) { for (... futures) { ... }}, you should use an ExecutorCompletionService. It does what you are trying to do and it probably does it a lot better. There is a complete example in the API.
Future has a cancel(boolean) method that will interrupt the running thread if true is passed in
so replace the if(!cancelled) checks with if(Thread.interrupted()) and return when you got a interrupt (you're not currently)
note that this will reset the interrupted flag to false (so if(Thread.interrupted()&&Thread.interrupted()) will be false) if you don't want to reset it use Thread.currentThread().isInterrupted() this maintains the flag for subsequent checks
or you can reset the flag to interrupted with Thread.currentThread().interrupt();
besides that use this inside the waiting while
for(Iterator<Future<MtaMigrationStatus>> it = futures.iterator();it.hasNext();){
Future<MtaMigrationStatus> future = it.next();
try
{
if (future.isDone())
{
it.remove();//<<--this avoids concurrent modification exception in the loop
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
if (futures.size() == 0)//outside the inner for loop and inside the while (or make the condition this) for micro-optimizing this check
{
done = true;
}
Your ElementProcessor can extend from java.util.concurrent.FutureTask which is
A cancellable asynchronous computation. This class provides a base
implementation of Future, with methods to start and cancel a
computation, query to see if the computation is complete, and retrieve
the result of the computation.
The FutureTask class is an implementation of Future that implements
Runnable, and so may be executed by an Executor.
FutureTask has a cancel method which you can implement to do some cancel specific operations. Also, if FutureTask is canceled it will not be executed anymore, so you don't have to check always the status.
In attempts of 100% code coverage, I came across a situation where I need to unit test block of code that catches an InterruptedException. How does one correctly unit test this? (JUnit 4 syntax please)
private final LinkedBlockingQueue<ExampleMessage> m_Queue;
public void addMessage(ExampleMessage hm) {
if( hm!=null){
try {
m_Queue.put(hm);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right before invoking addMessage(), call Thread.currentThread().interrupt(). This will set the "interrupt" status flag on the thread.
If the interrupted status is set when the call to put() is made on a LinkedBlockingQueue, an InterruptedException will be raised, even if no waiting is required for the put (the lock is un-contended).
By the way, some efforts to reach 100% coverage are counter-productive and can actually degrade the quality of code.
Use a mocking library like Easymock and inject a mock LinkedBlockingQueue
i.e.
#Test(expected=InterruptedException.class)
public void testInterruptedException() {
LinkedBlockingQueue queue = EasyMock.createMock(LinkedBlockingQueue.class);
ExampleMessage message = new ExampleMessage();
queue.put(message);
EasyMock.expectLastCall.andThrow(new InterruptedException());
replay(queue);
someObject.setQueue(queue);
someObject.addMessage(msg);
}
As stated above just make use Thread.currentThread().interrupt() if you caught InterruptedException and isn't going to rethrow it.
As for the unit testing. Test this way: Assertions.assertThat(Thread.interrupted()).isTrue();. It both checks that the thread was interrupted and clears the interruption flag so that it won't break other test, code coverage or anything below.
Another option is to delegate dealing with InterruptedException to Guava's Uninterruptibles, so you don't need to write and test your custom code for it:
import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;
private final LinkedBlockingQueue<ExampleMessage> queue;
public void addMessage(ExampleMessage message) {
putUninterruptibly(queue, message);
}
One proper way could be customizing/injecting the ThreadFactory for the executorservice and from within the thread factory, you got the handle of the thread created, then you can schedule some task to interrupt the thread being interested.
Demo code part for the overwrited method "newThread" in ThreadFactory:
ThreadFactory customThreadfactory new ThreadFactory() {
public Thread newThread(Runnable runnable) {
final Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
scheduledExecutorService.schedule(new Callable<String>() {
public String call() throws Exception {
System.out.println("Executed!");
thread.interrupt();
return "Called!";
}
},
5,
TimeUnit.SECONDS);
return thread;
}
}
Then you can use below to construct your executorservice instance:
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
Then after 5 seconds, an interrupt signal will be sent to the threads in a way each thread will be interrupted once in executorservice.
The example code in the question may be testable by calling Thread.currentThread().interrupt(). However, besides the mentioned problems various methods reset the interrupted flag. An extensive list is for example here: https://stackoverflow.com/a/12339487/2952093. There may be other methods as well.
Assuming waiting implemented as follows should be tested:
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException ex) {
// Set the interrupt flag, this is best practice for library code
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
A call to Thread.sleep itself clears the interrupted flag, so it cannot be set in advance. It can be tested using its own test thread as follows:
AtomicBoolean threadInterrupted = new AtomicBoolean(false);
Runnable toBeInterrupted = () -> {
try {
methodUnderTest();
} catch (RuntimeException unused) {
// Expected exception
threadInterrupted.set(true);
}
};
// Execute the in an operation test thread
Thread testThread = new Thread(toBeInterrupted);
testThread.start();
// When the test thread is waiting, interrupt
while (!threadInterrupted.get()) {
if (testThread.getState() == Thread.State.TIMED_WAITING) {
testThread.interrupt();
}
}
// Assert that the interrupted state is re-set after catching the exception
// Must be happening before thread is joined, as this will clear the flag
assertThat(testThread.isInterrupted(), is(true));
testThread.join();
I'm using a thread that is continuously reading from a queue.
Something like:
public void run() {
Object obj;
while(true) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}
What is the best way to stop this thread?
I see two options:
1 - Since Thread.stop() is deprecated, I can implement a stopThisThread() method that uses a n atomic check-condition variable.
2 - Send a Death Event object or something like that to the queue. When the thread fetches a death event, it exits.
I prefer the 1st way, however, I don't know when to call the stopThisThread() method, as something might be on it's way to the queue and the stop signal can arrive first (not desirable).
Any suggestions?
The DeathEvent (or as it is often call, "poison pill") approach works well if you need to complete all of the work on the queue before shutting down. The problem is that this could take a long time.
If you want to stop as soon as possible, I suggest you do this
BlockingQueue<O> queue = ...
...
public void run() {
try {
// The following test is necessary to get fast interrupts. If
// it is replaced with 'true', the queue will be drained before
// the interrupt is noticed. (Thanks Tim)
while (!Thread.interrupted()) {
O obj = queue.take();
doSomething(obj);
}
} catch (InterruptedException ex) {
// We are done.
}
}
To stop the thread t that instantiated with that run method, simply call t.interrupt();.
If you compare the code above with other answers, you will notice how using a BlockingQueue and Thread.interrupt() simplifies the solution.
I would also claim that an extra stop flag is unnecessary, and in the big picture, potentially harmful. A well-behaved worker thread should respect an interrupt. An unexpected interrupt simply means that the worker is being run in a context that the original programmer did not anticipate. The best thing is if the worker to does what it is told to do ... i.e. it should stop ... whether or not this fits with the original programmer's conception.
Why not use a scheduler which you simply can stop when required? The standard scheduler supports repeated scheduling which also waits for the worker thread to finish before rescheduling a new run.
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(myThread, 1, 10, TimeUnit.SECONDS);
this sample would run your thread with a delay of 10 sec, that means when one run finishes, it restarts it 10 seconds later. And instead of having to reinvent the wheel you get
service.shutdown()
the while(true) is not necessary anymore.
ScheduledExecutorService Javadoc
In your reader thread have a boolean variable stop. When you wish for this thread to stop set thius to true and interrupt the thread. Within the reader thread when safe (when you don't have an unprocessed object) check the status of the stop variable and return out of the loop if set. as per below.
public class readerThread extends Thread{
private volitile boolean stop = false;
public void stopSoon(){
stop = true;
this.interrupt();
}
public void run() {
Object obj;
while(true) {
if(stop){
return;
}
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(stop){
return;
}
obj = objectesQueue.poll();
// Do something with the Object obj
}
}
}
}
public class OtherClass{
ThreadReader reader;
private void start(){
reader = ...;
reader.start();
}
private void stop(){
reader.stopSoon();
reader.join(); // Wait for thread to stop if nessasery.
}
}
Approach 1 is the preferred one.
Simply set a volatile stop field to true and call interrupt() on the running thread. This will force any I/O methods that wait to return with an InterruptedException (and if your library is written correctly this will be handled gracefully).
I think your two cases actually exhibit the same potential behavior. For the second case consider Thread A adds the DeathEvent after which Thread B adds a FooEvent. When your job Thread receives the DeathEvent there is still a FooEvent behind it, which is the same scenario you are describing in Option 1, unless you try to clear the queue before returning, but then you are essentially keeping the thread alive, when what you are trying to do is stop it.
I agree with you that the first option is more desirable. A potential solution would depend on how your queue is populated. If it is a part of your work thread class you could have your stopThisThread() method set a flag that would return an appropriate value (or throw Exception) from the enqueuing call i.e.:
MyThread extends Thread{
boolean running = true;
public void run(){
while(running){
try{
//process queue...
}catch(InterruptedExcpetion e){
...
}
}
}
public void stopThisThread(){
running = false;
interrupt();
}
public boolean enqueue(Object o){
if(!running){
return false;
OR
throw new ThreadNotRunningException();
}
queue.add(o);
return true;
}
}
It would then be the responsibility of the object attempting to enqueue the Event to deal with it appropriately, but at the least it will know that the event is not in the queue, and will not be processed.
I usually put a flag in the class that has the Thread in it and in my Thread code I would do. (NOTE: Instead of while(true) I do while(flag))
Then create a method in the class to set the flag to false;
private volatile bool flag = true;
public void stopThread()
{
flag = false;
}
public void run() {
Object obj;
while(flag) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}