Android repeating task with timeout in Java - java

I've a problem with repeated tasks.
Basically, I'm working on service, which sends sms and check response for a minute. If response received, I update textview with success message otherwise fail.
My send sms service works ok, but I am stuck at receiving the sms.
I call send sms and check sms like this:
sendSms("6617", "Test") // it works;
readSms.run() // it works too;
if (message.equals("desired sms"){ // it doesn't wait read sms to finish
updateTextView("Success");
}
else{
updateTextView("Fail");
}
Here is readSms:
Runnable readSms = new Runnable(){
receivedMessage = "";
#Override
public void run() {
try {
//..checking sms..//
if (smsreceived) {message=receivedMessage;}
} finally {
mHandler.postDelayed(readSms, mInterval);
}
}
};
How can I make readSms to wait 60 seconds timeout with 1 second interval. If sms received, I should update textview with success, if not I'll wait until timeout and set textview with fail.

What you can do is:
Create a thread pool
Submit your task as a Callable to the thread pool
Wait a minute for a result
Create your thread pool using Executors like this for example:
// Create a thread pool composed of only one thread in this case
ExecutorService executor = Executors.newSingleThreadExecutor();
Submit your task as a Callable
Future<String> result = executor.submit(new Callable<String>(){
#Override
public String call() {
try {
//..checking sms..//
if (smsreceived) {return receivedMessage;}
return null;
} finally {
mHandler.postDelayed(readSms, mInterval);
}
}
});
Wait a minute for a result
try {
String receivedMessage = result.get(1, TimeUnit.MINUTES);
} catch (TimeoutException e) {
// ok let's give up
}
If the result cannot be retrieved within 1 minute the get method will throw a TimeoutException.
NB: The thread pool must not be created at each call, it must be created once for all in your class in order to reuse it at each call.

Related

when I use netty ctx.writeAndFlush(),the client does not receive a response

Java development, using netty's channel When writeandflush is executed in a new thread, the client does not receive a response; It can be received when executed in the normal method
private READER_ERR initReader() {
//not receive
new Thread(new Runnable() {
#Override
public void run() {
Channel channel = NettyChannelMap.get(clientId);
if (channel != null) {
ChatDto returnDto = new ChatDto();
returnDto.setClientId(clientId).setMsgType("READ").setMsg("返回数据");
channel.writeAndFlush(JSON.toJSONString(returnDto));
}
}
}).start();
//receive
Channel channel = NettyChannelMap.get(clientId);
if (channel != null) {
ChatDto returnDto = new ChatDto();
returnDto.setClientId(clientId).setMsgType("READ").setMsg("返回数据");
channel.writeAndFlush(JSON.toJSONString(returnDto));
}
}
The interrupt point debugs the netty source code and finds that it enters the AbstractChannelHandlerContext class
if (executor.inEventLoop()) {
if (flush) {
next.invokeWriteAndFlush(m, promise);
} else {
next.invokeWrite(m, promise);
}
} else {
AbstractChannelHandlerContext.WriteTask task = AbstractChannelHandlerContext.WriteTask.newInstance(next, m, promise, flush);
if (!safeExecute(executor, task, promise, m, !flush)) {
task.cancel();
}
}
We can see
public boolean inEventLoop(Thread thread) {
return thread == this.thread;
}
false is returned, it indicates that the thread has been started, and the thread does not belong to EventLoop. It is a thread created by the user. Therefore, netty creates a task internally and puts it into the queue for execution. The problem is that this queue has not been executed, and there is no place to forcibly find the task for execution.
Add a point: if the client receives the message normally, entering ineventloop() will return true, indicating that if the current thread belongs to EventLoop, it can be executed immediately.
Now you need to send messages to the client multiple times in a callback method, so how can the server actively send messages to the client in the new thread?
I tried again and found that if the last message was sent by the ineventloop worker thread, those messages that were not sent before will also be sent along with the messages of the last worker thread according to the insertion time sequence. For example, when the program runs, the order of messages added is 1, 2, 3, and the "end" sent by a worker thread is added, then the order of messages received by the client is: end, 1, 2, 3

Timelimiter is not interrupting the thread

I am using resilience4j Timelimiter in my project.
The timelimiter is throwing an error if a request is taking more than 10s, but it is not interrupting the thread.
When call comes from postman, i have put the debug and tested, after 10s in postman it displays an exception, but the thread still executes the method and after that added some print statements and it executed as well.
How to cancel or interrupt the thread after 10s in resilience4j.
class A {
TimeLimiterConfig config = TimeLimiterConfig.custom().cancelRunningFuture(true)
.timeoutDuration(Duration.ofMillis(TimeLimit)).build();
TimeLimiterRegistry timeLimiterRegistry = TimeLimiterRegistry.of(config);
TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter("APITimelimiter", config);
public Response someMethod() throws Exception {
try {
timeLimiter.executeFutureSupplier(() -> CompletableFuture.supplyAsync(() -> {
return getData();
}));
} catch (Exception e) {
logger.error("Request has crossed the execution time of " + TimeLimit
+ " seconds");
throw new Exception("Your request has crossed the execution time of "+ TimeLimit+" seconds.");
}
}
public UserData getData() {
String jsonData = "";
return jsonData;
}
}
TimeLimiter cannot cancel a CompletableFuture. See #TimeLimiter times out slow method but does not cancel running future #905 Points out, that: the limited cancel() in case of CompletableFuture is not a bug, but a design decision. CompletableFuture is not inherently bound to any thread, while Future almost always represents background task.

Is it possible to check time being taken by a method call in parallel

In a Spring Boot service class, let's say that I am making a method call processEvent().
The method processEvent() might be doing N number of things including making REST calls to other services.
How to check the time being taken by the method in parallel and if it crosses the threshold, then do something else e.g. throw exception ?
class EventService {
public void processEvent(ServiceContext context, Event event) {
// Field a time checker here for the below method.
processEvent(event);
}
public void processEvent(Event event) {
// this method does many things.
}
}
Can this be achieved using CompletionService ? If yes, Please give an example!
EDIT:
The following code works but I have one query:
public void processEvent(ServiceContext context, Event event) {
LOGGER.debug("Timestamp before submitting task = {}", System.currentTimeMillis());
Future<EventResponse> future = executor.submit(() -> {
LOGGER.debug("Timestamp before invoking = {}", System.currentTimeMillis());
EventResponse eventResponse = processEvent(event);
LOGGER.debug("Timestamp after invoking = {}", System.currentTimeMillis());
return eventResponse;
});
try {
LOGGER.debug("Thread sleep starts at = {}", System.currentTimeMillis());
Thread.sleep(5000);
LOGGER.debug("Thread sleep ended at = {}", System.currentTimeMillis());
} catch (InterruptedException e) {
LOGGER.debug("Going to print stack trace....");
e.printStackTrace();
}
if (!future.isDone()) {
future.cancel(true);
LOGGER.debug("task executor cancelled at = {}", System.currentTimeMillis());
} else {
EventResponse response = future.get();
LOGGER.debug("Received Event ID = {}", response.getEventDetailsList().get(0).getEventID());
return response;
}
LOGGER.debug("Going to return error response at = {}", System.currentTimeMillis());
throw new Exception("Message");
}
I am getting the below logs:
Timestamp before submitting task = 1579005638324
Thread sleep starts at = 1579005638326
Timestamp before invoking = 1579005638326
Thread sleep ended at = 1579005638526
task executor cancelled at = 1579005638527
Going to return error response at = 1579005638527
Timestamp after invoking = 1579005645228
How "Timestamp after invoking" is logged after "task executor cancelled at" ?
You can use ThreadPoolTaskExecutor to submit the task, then sleep for a certain amount of time, then check if the task is completed and interrupt it, if it's still working. However, you can't just kill the task, you'll have to periodically check for the interrupted flag inside the task itself. The code would be something like:
#Autowired
private ThreadPoolTaskExecutor executor;
// ...
Future<?> future = executor.submit(() -> {
doOneThing();
if(Thread.interrupted()) {
return;
}
doAnotherThing();
if(Thread.interrupted()) {
return;
}
// etc.
});
Thread.sleep(10000);
if (!future.isDone()) {
future.cancel(true);
}
You can use a mix of a standard ThreadPoolExecutor with a ScheduledThreadPoolExecutor. The latter will cancel the submission of the former if it's still running.
ThreadPoolExecutor executor = ...;
ScheduledThreadPoolExecutor watcher = ...;
Future<?> future = executor.submit(() -> { ... })
watcher.schedule(() -> future.cancel(true), THRESHOLD_SECONDS, TimeUnit.SECONDS);
The future.cancel(true) will be a no-op if it completed. For this though, you should be aware of how to handle cross-thread communiccation and cancellation. cancel(true) says "Either prevent this from running entirely, or, if it is running, interrupt the thread indicating we need to stop execution entirely and immediately"
From there your Runnable should handle interruption as a stop condition:
executor.submit(()-> {
// do something
if(Thread.currentThread().isInterrupted()) {
// clean up and exit early
}
// continue doing something
});

Java : ExecutorService : newFixedThreadPool

This may be bit old question. I am confused with the ExecutorService work in Jboss environment. I used some sample code, where i am submitting the task with ExecutorService and after everything is done i am shutdown the executor.
Problem i am facing is after submitting one request, i am getting below exception for subsequent request.
Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask#518ad6a2 rejected from java.util.concurrent.ThreadPoolExecutor#72114f80[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
ExecutorService executorService = Executors.newFixedThreadPool(3);
#POST
#Path("/request")
public Response checkAsync(final MultiMedia multiMedia) {
final Random rand = new Random();
final String random = String.valueOf(rand.nextInt(50) + 1);
multiMediaJobs.put(random, multiMedia);
final String jobId = "{ 'jobId' : " + random + "}";
executorService.submit(new Runnable() {
#Override
public void run() {
boolean result = veryExpensiveOperation(jobId);
if (result) {
try {
MultiMedia multiMedia = (MultiMedia) multiMediaJobs.get(random);
multiMedia.getMediadata().getMetadata()
.setAssetId(random);
final String uri = multiMedia.getCallback().getUri()+multiMedia.getCallback().getResource();
RestTemplate restTemplate = new RestTemplate();
String code = restTemplate.postForObject(uri,
multiMedia, String.class);
System.out.println(code);
} finally {
logger.debug("Map size: " + multiMediaJobs.size());
logger.debug("Time: "+System.currentTimeMillis());
multiMediaJobs.remove(random);
}
}
}
private boolean veryExpensiveOperation(String jobId) {
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.debug("Task is processed fully");
return true;
}
});
executorService.shutdown();
try {
executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Response.status(Status.ACCEPTED)
.entity(commonHelper.toJSON(jobId)).build();
}
Is it really required to call shutdown in JBOSS environment? If i remove that it is accept all my request. Example i am seeing in all here is just main method. I just want to know how it works in real application.
Forgive me if i am misunderstood some concept.
The problem is that you shutdown the ExecutorService. So any subsequent task being submitted is rejected right away.
I think you have some misunderstanding here.
When you submit to an executor, you will normally get a Future<T> object back. If you need a result from this, you'll call Future.get() and that will block until the threadpool executes your job. Otherwise you can just leave your jobs to be executed.
You wouldn't normally shutdown the executor unless you really want to shut it down, not accept any jobs, and let those queued up execute.

Synchronization in threads for Java

I have a home grown web server in my app. This web server spawns a new thread for every request that comes into the socket to be accepted. I want the web server to wait until a specific point is hit in the thread it just created.
I have been through many posts on this site and examples on the web, but cant get the web server to proceed after I tell the thread to wait. A basic code example would be great.
Is the synchronized keyword the correct way to go about this? If so, how can this be achieved? Code examples are below of my app:
Web Server
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.run();
///////////////////////////////
wait here until notifed to proceed
///////////////////////////////
} catch (Exception e) {
e.printStackTrace(logFile);
}
}
Thread code
public void run() {
//code here
//notify web server to continue here
}
Update - Final code is as below. The HttpRequest does just call resumeListener.resume() whenever I send a response header (of course also adding the interface as a separate class and the addResumeListener(ResumeListener r1) method in HttpRequest):
Web Server portion
// server infinite loop
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
request.addResumeListener(new ResumeListener() {
public void resume() {
//get control of the lock and release the server
synchronized(locker) {
locker.notify();
}
}
});
synchronized(locker) {
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.start();
//tell this thread to wait until HttpRequest releases
//the server
locker.wait();
}
} catch (Exception e) {
e.printStackTrace(Session.logFile);
}
}
You can use java.util.concurrent.CountDownLatch with a count of 1 for this. Arrange for an instance of it to be created and shared by the parent and child thread (for example, create it in HttpRequest's constructor, and have it retrievable by a member function). The server then calls await() on it, and the thread hits countDown() when it's ready to release its parent.
You probably need to use a Java Condition. From the docs:
Conditions (also known as condition
queues or condition variables) provide
a means for one thread to suspend
execution (to "wait") until notified
by another thread that some state
condition may now be true.
First of all, I echo the sentiment of others that re-inventing the wheel here will most likely lead to a variety of issues for you. However, if you want to go down this road anyway what you are trying to do is not difficult. Have you experimented with Jetty?
Maybe something like this:
public class MyWebServer {
public void foo() throws IOException {
while (true) {
//block here until a connection request is made
ServerSocket socket = new ServerSocket();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
MyRequest request = new MyRequest(socket);
request.addResumeListener(new ResumeListener() {
public void resume() {
locker.notify();
}
});
synchronized(locker){
//create a new thread for each request
Thread thread = new Thread(request);
//start() the thread - not run()
thread.start();
//this thread will block until the MyRequest run method calls resume
locker.wait();
}
} catch (Exception e) {
}
}
}
}
public interface ResumeListener {
public void resume();
}
public class MyRequest implements Runnable{
private ResumeListener resumeListener;
public MyRequest(ServerSocket socket) {
}
public void run() {
// do something
resumeListener.resume(); //notify server to continue accepting next request
}
public void addResumeListener(ResumeListener rl) {
this.resumeListener = rl;
}
}
Run under a debugger and set a breakpoint?
If unfeasible, then read a line from System.in?

Categories