I am attempting to run multiple services parallely using ExecutorService. But i failed to execute parallely.
I have written java.util.concurrent.TimeUnit.MINUTES.sleep(1) to wait one minute in Service1 class.
But Service2 is processing only after Service1 processed.
Below is my code snippet, Kindly correct me/code if my understand about ExecutorService is wrong
public void startService() {
try {
ExecutorService service = Executors.newFixedThreadPool(3);
service.submit(new Service1());
service.submit(new Service2());
service.submit(new Service3());
service.shutdown();
service.awaitTermination(1, TimeUnit.MINUTES);
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public class Service1 implements Callable<Object> {
{
try {
java.util.concurrent.TimeUnit.MINUTES.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Object call() throws Exception {
return null;
}
}
public class Service2 implements Callable<Object> {
#Override
public Object call() throws Exception {
System.out.println(" Service 2 "); // It prints after 1 minute only.
return null;
}
}
public class Service3 implements Callable<Object> {
#Override
public Object call() throws Exception {
System.out.println(" Service 3 ");
return null;
}
}
The code:
{
try {
java.util.concurrent.TimeUnit.MINUTES.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
is a constructor, and it is called by the main thread when it's doing new Service1().
So yeah, it must complete before it has a chance to submit the services.
UPDATE:
In your original post, the sleep was in the call method, and it worked. Now, your Service1 is equivalent to:
public class Service1 implements Callable<Object> {
public Service1() {
try {
java.util.concurrent.TimeUnit.MINUTES.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Object call() throws Exception {
return null;
}
}
And only the call method is run by the executor. the Service1 instance cannot even be submitted before the constructor completes.
Related
The code I want to achieve is as below:
StreamSupport.stream(jsonArray.spliterator(), true).forEach(s ->{
try {
//invoke other api and set timeout for its execution
}
catch(TimeoutException e) {
s.getAsJsonObject().addProperty("processStatus", "Failure");
}
});
Can anyone help me in achieving "invoke other api and set timeout for it's execution" case in the above snippet?
I don't think you can do that inside a stream, but you can wrap the execution in a Callable like so to achieve the same result:
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println(future.get(1, TimeUnit.SECONDS));
}catch (Exception e) {
future.cancel(true);
e.printStackTrace();
} finally {
executor.shutdownNow();
}
}
private static class Task implements Callable<String> {
#Override
public String call(){
IntStream.of(1,2,3,4,5,6,7,8,9).parallel().forEach(t -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
return "ok";
}
}
I'm wiriting a Spring Boot app for simulating an events generator of syslog. With a rest call I have to start the events generation and with another rest call I have to stop it. To achieve that, I created an ExecutorService with a single thread with a for loop inside the Runnable, but it does not stop at all. I tried to break the for loop with Thread.currentThread().isInterrupted after the shutdownNow() but it seems that it does not set the IsInterrupted to true. If I use the loop boolean, of course the loop stop but I can't create new thread with a 500 server error.
That's my code:
#Service
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class EventService {
final static Logger logger = LoggerFactory.getLogger(EventService.class);
private ConfigReader configReader;
private static ExecutorService executor = Executors.newFixedThreadPool(2);
private EventsGenerator eventsGen;
private String test;
public EventService(ConfigReader configReader) {
this.configReader = configReader;
}
public void init(byte[] fileConfig) throws IOException {
configReader.read(fileConfig);
eventsGen = new EventsGenerator(configReader,configReader.getConfig().getProtocol());
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
eventsGen.stop();
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
logger.error(e.getMessage());
}
}
});
executor.execute(eventsGen);
executor.shutdown();
/*
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS );
} catch (InterruptedException e) {
logger.error(e.getMessage());
}
*/
}
public void shutdownService() {
eventsGen.stop();
executor.shutdownNow();
}
}
Run method of eventsGenerator:
#Override
public void run() {
//other things
int it;
for(i=0;i<max;i++) {
try {
if(Thread.currentThread().isInterrupted()) {
break;
}
if(!loop){
break;
}
NStringTemplate template = getNextTemplate();
String message = template.buildString(context);
if(config.getEndTime() != null) {
Date currentTime = context.getTime(false);
if(currentTime.after(config.getEndTime())) {
logger.info("L'endTime รจ stato superato");
break;
}
}
//other business logic
}catch(Exception exc){}
}
public void stop(){
setLoop(false);
}
I set 2 services in my web.xml and I create for each a shedule service as this:
public class MyScheduler implements ServletContextListener {
private ScheduledExecutorService scheduledExecutorService = null;
#Override
public void contextInitialized(ServletContextEvent sce) {
if ((scheduledExecutorService == null) || (!scheduledExecutorService.isTerminated())) {
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new MyScheduledTimer(), 0, 15, TimeUnit.DAYS);
}
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
try {
scheduledExecutorService.shutdown();
} catch (Exception ex) {
}
}
}
class MyScheduledTimer extends TimerTask {
{
try {
MyEjb ejbObject = (InterfaceEjb) new InitialContext().lookup("java:global/project/MyEjb");
} catch (NamingException ex) {
Logger.getLogger(MyScheduler.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
Logger.getLogger(MyScheduler.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void run() {
//my code to run with ejbObject...
}
}
I would like to run first service to startup my application, waiting that this service is completed and after run the second service. Is it possibile?
If you want to use something more specific - you can use CountDownLatch for example. Create
CountDownLatch latch = new CoundownLatch(1);
First service will call countDown(), when finishes his work.
//service1
public void run(){
doSmthng();
latch.countDown();
}
And second service will wait until latch counter not equals 0.
//service2
public void run(){
latch.await();
doSmthngElse();
}
I have an inner class that extends Thread
private class TestStart extends Thread {
public void run() {
try {
startServer();
}
catch (Exception e) {
/// How to handle it?
}
}
}
The caller in the main thread:
public void start() throws Exception {
Thread st = new TestStart();
st.start();
}
Method startServer() throws Exception by its API, so I have to use try-catch as Thread.run() does not "throws" exception in method definition. I need to bubble up the caught exception into the main thread to handle it. Is there an easy way to do it? Thanks
If you use an ExecutorService instead of using raw threads, you can be notified of uncaught exceptions:
class MyCallable implements Callable<Void> {
#Override public Void call() throws Exception {
// Do something - you don't need to catch Exception as Callable throws it.
// ...
return null; // A return is necessary from a Callable.
}
}
Create an executor service somewhere, e.g.:
ExecutorService executor = Executors.newFixedThreadPool(1);
Then, in the code where you start the thread:
Future<?> future = executor.submit(new MyCallable());
try {
future.get(); // Blocks until the Callable completes.
} catch (ExecutionException e) {
// You reach here if an exception is thrown in the Callable -
// The exception is accessible via e.getCause().
}
Set a new exception handler on your Thread.
st.setDefaultUncaughtExceptionHandler(new Thread.
UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t + " throws exception: " + e);
}
});
And place that code before your start();
There is a few possible solutions. For example:
Use setUncaughtExceptionHandler()/setDefaultUncaughtExceptionHandler() and change your try/catch
try {
startServer();
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
Or use your custom listener
private class TestStart extends Thread {
private final ServerStateListener lnr;
TestStart(ServerStateListener lnr) {
this.lnr = lnr;
}
public void run() {
try {
startServer();
lnr.onServerStarted();
}
catch (Exception e) {
lnr.onServerStoppedByError(e);
}
}
}
Or just save Exception and read it after .join
private class TestStart extends Thread {
private Exception error; // if you start and join and read this property within one thread, you don't need to use volatile, otherwise do it for safe publication
public void run() {
try {
startServer();
}
catch (Exception e) {
error = e;
}
}
public Exception getError() {
return error;
}
}
Or use ExecutorService/Callable instead of your own thread as Andy suggested.
I'm computing a future for having a timeout in waiting for a serial event to happen:
Future<Response> future = executor.submit(new CommunicationTask(this, request));
response = new Response("timeout");
try {
response = future.get(timeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (InterruptedException | TimeoutException e) {
future.cancel(true);
log.info("Execution time out." + e);
} catch (ExecutionException e) {
future.cancel(true);
log.error("Encountered problem communicating with device: " + e);
}
The CommunicationTask class has implemented the Observer interface to listen to an change from the serial port.
The problem is that reading from the serial port is relatively slow and even when a serial event is happening the time runs out and a TimeoutException is thrown. What can I do to stop the timeout clock of my future when a serial event is happening?
I tried it with an AtomicReference but that didn't change anything:
public class CommunicationTask implements Callable<Response>, Observer {
private AtomicReference atomicResponse = new AtomicReference(new Response("timeout"));
private CountDownLatch latch = new CountDownLatch(1);
private SerialPort port;
CommunicationTask(SerialCommunicator communicator, Request request) {
this.communicator = communicator;
this.message = request.serialize();
this.port = communicator.getPort();
}
#Override
public Response call() throws Exception {
return query(message);
}
public Response query(String message) {
communicator.getListener().addObserver(this);
message = message + "\r\n";
try {
port.writeString(message);
} catch (Exception e) {
log.warn("Could not write to port: " + e);
communicator.disconnect();
}
try {
latch.await();
} catch (InterruptedException e) {
log.info("Execution time out.");
}
communicator.getListener().deleteObserver(this);
return (Response)atomicResponse.get();
}
#Override
public void update(Observable o, Object arg) {
atomicResponse.set((Response)arg);
latch.countDown();
}
}
What can I do to solve this problem?
EDIT:
Ok I had one error. I was counting down my latch befor setting the atomicResponse in my update function. Now it seems to work, but there's still the question if this approach is the right way to do so?
have you explored google's Guava 'future listener', it is based on Async future, hope following code snippet helps you....
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class SyncFutureExample {
public static void main(String[] args) {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
ListenableFuture<String> lf = service.submit(new CommuncationTask());
//no need for future.get() or future.get(10,time minutes)
//add callbacks(= async future listeners) ....
Futures.addCallback(lf, new FutureCallback<String>() {
public void onSuccess(String input) {
System.out.println(input + " >>> success");//gets a callback once task is success
}
public void onFailure(Throwable thrown) {
System.out.println(thrown + " >>> failure");//gets a callback if task is failed
}
});
service.shutdown();
}
}
class CommuncationTask implements Callable<String>{
public String call() throws Exception {
TimeUnit.SECONDS.sleep(15);// some dummy serious task .............
return "TaskDone";
}
}
Hope this will help. I won't comment on it in the hopes that everything is clear from the code.
class CommunicationTask implements Callable<String>, Observer {
volatile boolean ignoreTimeoutException;
public CommunicationTask(SerialCommunicator communicator, Request request) {
}
public String call() throws Exception {
Thread.sleep(1000);
return "done";
}
public void update(Observable o, Object arg) {
ignoreTimeoutException = true;
}
}
class FutureCommunicationTask extends FutureTask<String> {
private CommunicationTask ct;
public FutureCommunicationTask(CommunicationTask ct) {
super(ct);
this.ct = ct;
}
public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
try {
return super.get(timeout, unit);
} catch (TimeoutException e) {
if (ct.ignoreTimeoutException) {
return get(); // no timeout wait
}
throw e;
}
}
}
public class Test {
public static void main(String[] args) throws Exception {
CommunicationTask ct = new CommunicationTask(null, null);
FutureTask<String> fct = new FutureCommunicationTask(ct);
ExecutorService ex = Executors.newSingleThreadExecutor();
ex.execute(fct);
// uncomment this line and timeout will be cancelled
ct.update(null, null);
String res = fct.get(1, TimeUnit.MILLISECONDS);
System.out.println(res);
}
}