I'm using this code to Schedule a Task in my Java 8 Spring WebApp:
In a #Controller;
#EventListener(ContextRefreshedEvent.class)
public void doSomethingAfterContextRefreshed() {
ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
#Override
public void run() {
try {
Execute();
} catch (IOException e) {
e.printStackTrace();
}
}}, 10, TimeUnit.SECONDS);
while (!countdown.isDone()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
scheduler.shutdown();
}
When the App starts, the Execute() method gets called 10 seconds after startup with no errors, but after it completes I get the following stack trace:
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask#52518e6[Not completed, task = java.util.concurrent.Executors$RunnableAdapter#759546c8[Wrapped task = com.mycompany.myproject.service.LoadService$1#4871ba3f]] rejected from java.util.concurrent.ScheduledThreadPoolExecutor#798daafa[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]
at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:340)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:562)
Any ideas why I get this exception?
Let's simplify this:
public class DeleteMe {
public static void main(String[] args) {
doSomethingAfterContextRefreshed();
doSomethingAfterContextRefreshed();
}
static ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
public static void doSomethingAfterContextRefreshed() {
ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Some message");
}}, 100, TimeUnit.MILLISECONDS);
while (!countdown.isDone()) {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(10));
}
scheduler.shutdown();
}
}
At the end of the first invocation of doSomethingAfterContextRefreshed - what do you do? scheduler.shutdown();.
At the second invocation of doSomethingAfterContextRefreshed(); what do you do? scheduler.schedule(....).
Is the scheduler shutdown at this point in time? What does the documentation of schedule says to throw in such cases? You have your answer now.
Related
This question already has answers here:
RejectedExecutionException inside single executor service
(1 answer)
Can java finalize an object when it is still in scope?
(2 answers)
Closed 3 years ago.
This is a multi-threaded test code, each time a newSingleThreadExecutor is created, and two other threads are constantly triggering gc. Under HotSpot java8 (1.8.0_221), there will be an error that the thread pool has been closed.
public class ThreadPoolTest {
public static void main(String[] args) {
final ThreadPoolTest threadPoolTest = new ThreadPoolTest();
for (int i = 0; i < 8; i++) {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
Future<String> future = threadPoolTest.submit();
try {
String s = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (Error e) {
e.printStackTrace();
}
}
}
}).start();
}
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
System.gc();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
System.gc();
}
}
}).start();
}
public Future<String> submit() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
FutureTask<String> futureTask = new FutureTask(new Callable() {
#Override
public Object call() throws Exception {
Thread.sleep(50);
return System.currentTimeMillis() + "";
}
});
executorService.execute(futureTask);
return futureTask;
}
}
After running for a while, you will get an error:
Exception in thread "Thread-2" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask#a5acd19 rejected from java.util.concurrent.ThreadPoolExecutor#30890a38[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:668)
at ThreadPoolTest.submit(ThreadPoolTest.java:54)
at ThreadPoolTest$1.run(ThreadPoolTest.java:12)
at java.lang.Thread.run(Thread.java:748)
Executors.newSingleThreadExecutor creates an auto-closed thread pool (java.util.concurrent.Executors.FinalizableDelegatedExecutorService), so it should only be executed shutdown before the object is collect.
But from the error log, the executorService was shutdown in advance. Like before the stack frame popped, the finalized method of the executorService was executed ahead of time.
Why does this happen?
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();
}
In my project I have a chart which can turn into an animation depending on if we click Start or Stop button. I can make it start, but I don't know how to stop it. Method shutdownNow() gives no result. How can I do this? Here is my code
public class Animation extends JPanel{
// initializations
ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
Animation(String s){
// initialization of chart and adding XYSeries
this.add(chartPanel);
}
public void go() {
scheduler.scheduleAtFixedRate( (new Runnable() {
#Override
public void run() {
double first;
l = dataset.getSeries();
while(true) {
first = (double)l.get(0).getY(0);
for (int k = 0; k < l.get(0).getItemCount(); k++) {
if (k + 1 < l.get(0).getItemCount()) l.get(0).updateByIndex(k, l.get(0).getY(k+1));
else l.get(0).updateByIndex(k, first);
}
}
}
}), 0, 5, MILLISECONDS);
}
public void stop() {
scheduler.shutdownNow();
}
}
As per java docs how shutdownNow() works like below.
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via {#link Thread#interrupt}, so any a task that fails to
respond to interrupts may never terminate.
So, it will set interrupted flag true, so you need to correctly manage the InterruptedException and / or explicitly check Thread.currentThread().isInterrupted(). You can use below code to stop your current running inputted thread.
while (!Thread.currentThread().isInterrupted()) {
// your code here
}
(!Thread.currentThread().isInterrupted())
may be a solution
but personally i would:
extract runner in method
stop runner by flipping a boolean
call scheduler.shutdownNow(); when needed (on close JPanel?)
example:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
boolean running;
public void setup() {
scheduler.scheduleAtFixedRate(runner(), 0, 5, TimeUnit.MILLISECONDS);
}
private Runnable runner() {
return () -> {
while (running) {
try {
//DO YOUR STUFF HERE
System.err.println("RUNNING");
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
public void go() {
running = true;
}
public void stop() {
running = false ;
}
public void shutdown() {
scheduler.shutdownNow();
}
public static void main(String[] args) throws InterruptedException {
Demo tasks = new Demo();
tasks.setup();
for (int i = 1; i <= 5; i++) {
System.err.println("GO FOR IT " + i);
tasks.go();
Thread.sleep(2000);
tasks.stop();
Thread.sleep(1000);
}
tasks.shutdown();
}
The idea is for my runnable to run every minute.
Instead, it runs in roughly about 20 seconds and I have no idea why.
Below is the code:
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
try{
//Post from Queue & update post
if (NetworkUtils.isConnected()) {
//post from queue
try {
postHelper.postFromQueue();
} catch (IOException e) {
e.printStackTrace();
}
//Update posts
postHelper.updateSolicitations();
}
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//also call the same runnable to call it at regular interval
handler.postDelayed(this, 60000);
}
}
};
I don't know if it's relevant but it's onCreate method of MainActivity.
Maybe you consider using ScheduledExecutorService
public static void main(String[] args) {
ScheduledExecutorService execService
= Executors.newScheduledThreadPool(5);
execService.scheduleAtFixedRate(()->{
//The repetitive task, say to update Database
System.out.println("hi there at: "+ new java.util.Date());
}, Delay, Rate, TimeUnit.MILLISECONDS );//TimeUnit.MILLISECONDS is time unit
}
Use a scheduled where you define a quartz cronjob that is then triggered whenever you defined it.
you can do something like every minute or second or every day at 3 o'clock
Simple Quartz/Cron job setup
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
try{
//Post from Queue & update post
if (NetworkUtils.isConnected()) {
//post from queue
try {
postHelper.postFromQueue();
} catch (IOException e) {
e.printStackTrace();
}
//Update posts
postHelper.updateSolicitations();
}
}
catch (Exception e) {
// TODO: handle exception
}
}
}, 60000);
I don't have previous experience with JAVA's concurrency, but ever done the same in C#.
My task
To create a "worker" class for easy multi-threading (creating continuous threads) managing in my applications.
what i want to have as result(usage example):
Worker worker = new Worker();
worker.threadCount = 10;
worker.doWork(myMethod);
worker.Stop();
to be able to use it in any class in my app, accepting 'void' methods as 'worker.doWork(myMethod);' argument.
What did i done from my researches on question:
class Worker
package commons.Threading;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
public class Worker {
static Boolean IsRunning = true;
public static int threadCount = 2;
static ExecutorService threadPool = new ErrorReportingThreadPoolExecutor(threadCount);
public void doWork(**argument method**) throws IOException, InterruptedException {
while (IsRunning) {
threadPool.submit(new Runnable() {
**argument method**
});
Thread.sleep(1000);
}
}
public static void Stop(){
IsRunning = false;
threadPool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
threadPool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
threadPool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
ErrorReportingThreadPoolExecutor
package commons.Threading;
import java.util.concurrent.*;
public class ErrorReportingThreadPoolExecutor extends ThreadPoolExecutor {
public ErrorReportingThreadPoolExecutor(int nThreads) {
super(nThreads, nThreads,
0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
#Override
protected void afterExecute(Runnable task, Throwable thrown) {
super.afterExecute(task, thrown);
if (thrown != null) {
// an unexpected exception happened inside ThreadPoolExecutor
thrown.printStackTrace();
}
if (task instanceof Future<?>) {
// try getting result
// if an exception happened in the job, it'll be thrown here
try {
Object result = ((Future<?>)task).get();
} catch (CancellationException e) {
// the job get canceled (may happen at any state)
e.printStackTrace();
} catch (ExecutionException e) {
// some uncaught exception happened during execution
e.printStackTrace();
} catch (InterruptedException e) {
// current thread is interrupted
// ignore, just re-throw
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) throws InterruptedException {
// replace
// ExecutorService threadPool = Executors.newFixedThreadPool(2);
// with
ExecutorService threadPool = new ErrorReportingThreadPoolExecutor(2);
while (true) {
threadPool.submit(new Runnable() {
#Override public void run() {
System.out.println("Job is running...");
if (Math.random() < 0.5) {
int q = 1 / 0;
}
System.out.println("Job finished.");
}
});
Thread.sleep(1000);
}
}
}
So, the question is - how do i pass 'void' method from outside class here threadPool.submit(new Runnable() { here });
You could pass the Runnable itself is a parameter,
public void doWork(Runnable runnable) throws IOException, InterruptedException {
while (IsRunning) {
threadPool.submit(runnable);
Thread.sleep(1000);
}
}
Runnable is a functional interface,it has a single method run that takes no-param and returns void, and hence you can use it as a function.
Runnable runnable = new Runnable(){
public void run(){
// do work
}
};
doWork(runnable);
You can express it more concisely if you are on Java 1.8
Runnable runnable = ()->{/**do work*/};
doWork(runnable);