How to stop working ScheduledExecutorService? - java

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();
}

Related

synchronise a method with runnable executing some async calls

I am working with a init() that need to be synchronise. But I have to run some set of instructions in init() which has to execute on main thread. So I created a runnable to add this instruction. And those instructions has some async calls.
So I am exploring efficient ways to block the init() untill all the instructions completes successfully.
Static void init() {
new Handler(context.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// doing some async calls
}
}
}
You need to synchronize the init() method and then use CompletionService to wait for Future to complete. Like so:
public synchronized void init() throws InterruptedException {
Executor executor = Executors.newFixedThreadPool(4);
CompletionService<String> completionService = new ExecutorCompletionService<String>(executor);
// 4 tasks
for (int i = 0; i < 4; i++) {
completionService.submit(new Callable<String>() {
public String call() {
return "i am an async task finished";
}
});
}
int received = 0;
boolean errors = false;
while (received < 4 && !errors) {
Future<String> resultFuture = completionService.take(); // blocks if none available
try {
String result = resultFuture.get();
System.out.println(result);
received++;
} catch (Exception e) {
errors = true;
/// some acceptable error handling;
}
}
}
I have taken the code from this thread and adopted it for your needs. Don't forget to handle InterruptedException properly like described here.

Ending console based multi threaded program gracefully

I have the following class, I usually run about 10 threads of it
public class MyClass implements Runnable {
private volatile Device device = null;
public MyClass(Device device) {
this.device = device;
}
#Override
public void run() {
while (true) { // <--- I do know that the "true" has to be changed to a Boolean
try {
Worker worker = new Worker();
worker.work();
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
}
and in my main I start the threads like this
for (int i = 0; i < 2; i++) {
(new Thread(new MyClass())).start();
}
This is a console based program. What is the most reliable way to end the program? I think the best way would be to change while (true) to while (Boolean) and somehow change that Boolean for all threads, then when the loop ends, the program will end gracefully.
Here i'm ending it by waiting for a user input but you can change it to fire the stop method from anywhere
public static void main(String[] args) {
List<MyClass> myThreads = new ArrayList<>();
for (int i = 0; i < 2; i++) {
MyClass myClass = new MyClass();
Thread t = new Thread(myClass);
t.start();
myThreads.add(myClass);
}
Scanner in = new Scanner(System.in);
in.next();
for(MyClass t : myThreads){
t.stop();
}
}
class MyClass implements Runnable {
private Boolean flag;
public MyClass() {
this.flag = true;
}
#Override
public void run() {
while (flag) { // <--- I do know that the "true" has to be changed to a Boolean
try {
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
public void stop(){
this.flag = false;
} }
The easy way would be to store all your threads in a set and make loop joining them at the end.
Be aware that this is not the most ortodox neither the most efficient way to do this.
In your main:
HashSet<Thread> threads = new HashSet();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new MyClass());
threads.add(t);
t.start();
}
for (Thread thread: threads) {
thread.join();
}
some more material
The following code uses an executor service to fix the number of threads that run at any time, it provides a Future object that also tells you when your thread has shutdown gracefully. They share a shutdown object as well. This offers you a bit more flexibility as the executor service can let you decide how many threads run at any one time gracefully.
First lets created a shared shutdown object that will notify all the threads it is time to shut down. There will be one instance of this and each thread will have a copy.
public static class Shutdown {
private boolean running;
public void shutdown() {
this.running = false;
}
public boolean isRunning() {
return running;
}
}
Next let me just create a dummy thread that does nothing more than sleep forever while it is running. Obviously you can simply replace this with your own thread to do something useful.
public static class MyClass implements Runnable {
final Shutdown shutdown;
public MyClass(Shutdown shutdown) {
this.shutdown = shutdown;
}
#Override
public void run() {
while (shutdown.isRunning()) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
System.out.println("Did not gracefully shut down");
}
}
System.out.println("Thread in program ended!");
}
}
}
Now for the main class which will run everything, this is where the magic happens.
public class Main {
public static void main(String[] args) {
//run exactly 10 threads at a time
ExecutorService executorService = Executors.newFixedThreadPool(10);
//this is how we shut it down
Shutdown globalShutdown = new Shutdown();
//start up the 10 threads
List<Future<?>> futures = new ArrayList<>();
for(int i = 0; i< 10; i++)
futures.add(executorService.submit(new MyClass(globalShutdown)));
//gracefully shut them down
globalShutdown.shutdown();
try {
//wait for them all to shutdown
for(Future<?> future : futures)
future.get();
} catch (InterruptedException e) {
throw new IllegalStateException("This should never happen");
} catch (ExecutionException e) {
throw new IllegalStateException("This should never happen");
}
//everything got shutdown!
}
in practice however you probably also want to handle the case where your thread may not end gracefully due to a bug. Rather than stall forever you might want to add a timeout and if that timeout is exceeded then simply forcibly terminate all remaining threads. To do that replace the above try-catch block with this.
try {
//wait for them all to shutdown
boolean timedout = false;
for(Future<?> future : futures) {
if( !timedout ) {
try {
future.get(30, TimeUnit.SECONDS);
} catch (TimeoutException e) {
timedout = true;
}
}
if(timedout) {
future.cancel(true);
}
}
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException("This should never happen");
}

Synchronized keyword doesn't work

package threadShareResource1;
public class NonSynchro1 {
private int sum = 0;
public static void main(String[] args) {
NonSynchro1 n = new NonSynchro1();
n.task();
System.out.println(n.getSum());
}
public synchronized void sumAddOne(){
sum++;
}
public void task(){
for (int i = 0; i < 100; i++) {
new Thread(new Runnable(){
#Override
public void run() {
sumAddOne();
}
}).start();
/* try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} */
}
}
public int getSum() {
return sum;
}
}
Without the commented part of code, the program has data corruption, which is not 100 every time I run it. But I thought the synchronized keyword should acquires a lock on the sumAddOne method, which is the critical region of my program, allowing one thread accessing this method every time.
I've try to use ExecutorService as well, but it doesn't give 100 all the runs.
public void task(){
ExecutorService s = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
s.execute(new Thread(new Runnable(){
#Override
public void run() {
sumAddOne();
}
}));
}
s.shutdown();
while(!s.isTerminated()){}
}
In Task(), you start 100 threads (which is a lot) and each one is to add 1 to sum.
But when Task is done all you know is that 100 threads are in some process of having started. You don't block before calling println(), so how do you know all the threads have completed?
The sleep probably "prevents the corruption" just because it gives the system time to finish launching all the threads.
Beyond that you are using Synchronized correctly. Any place multiple threads may write to the same variable you need it and, in general (simplifying), you don't need it if you are only reading.
Synchronised keyword is used correctly, the problem is that you are not waiting for the threads to finish. Here is a possible solution:
public class NonSynchro1 {
private static final ExecutorService executorService = Executors.newCachedThreadPool();
private int sum = 0;
public static void main(String[] args) {
NonSynchro1 n = new NonSynchro1();
n.task();
System.out.println(n.getSum());
executorService.shutdown();
}
public synchronized void sumAddOne() {
sum++;
}
public void task() {
List<Callable<Object>> callables = new ArrayList<>();
for (int i = 0; i < 100; i++) {
callables.add(() -> {
sumAddOne();
return null;
});
}
List<Future<Object>> futures;
try {
futures = executorService.invokeAll(callables);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
futures.forEach(future -> {
try {
future.get();
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
});
}
public int getSum() {
return sum;
}
}
First we create a list of callables - a list of functions that will be executed in parallel.
Then we invoke them on the executor service. newCachedThreadPool I have used here, by default has 0 threads, it will create as many as necessary to execute all passed callables, the threads will be killed after being idle for a minute.
Finally, in the for-each loop we resolve all futures. get() call will block until the function was executed by the executor service. It will also throw exception if it was thrown inside the function (without calling get() you would not see such exception at all).
Also, it is a good idea to shutdown the executor service when you want to terminate the program gracefully. In this case, it is just executorService.shutdown() at the end of main method. If you don't do this, the program will terminate after a minute when idle threads are killed. However, if different executor service, threads might not be killed when idle, in which case the program would never terminate.
Just for completeness sake: Here's a solution showing how the original program can be made to wait for all threads to finish by joining them:
for (Thread t : n.task())
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
which requires task to return the threads it creates. In this case we don't need to complicate things with caching managers or collections: a simple array will do. Here's the complete class:
public class TestSynchro1 {
private int sum = 0;
public synchronized void sumAddOne() {
sum++;
}
public Thread[] task(int n) {
Thread[] threads = new Thread[n];
for (int i = 0; i < n; i++) {
(threads[i] = new Thread(new Runnable() {
#Override
public void run() {
sumAddOne();
}
})).start();
}
return threads;
}
public static void main(String[] args) {
TestSynchro1 n = new TestSynchro1();
for (Thread t : n.task(100))
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(n.sum);
}
}

Execute certain amount of thread in a for loop

I want to build an application that executes a certain utility with multi threads. I want to control the amount of threads. Here is what I want to do:
//initialize the number of threads to be 10
for(int i = 0; i < BIG_VALUE; i++) {
RunnableObject rb = new RunnableObject(i);
rb.run();
//the for loop should run for 10 loops. When one of the threads finish its job
//the for loop continues and runs another thread. The amount of threads should
//always be 10
}
How can I do so in Java?
You can try with Java Executor framework http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html
Here an example of how to used
public class SimpleThreadPool {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread('' + i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println('Finished all threads');
}
}
public class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s){
this.command=s;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName()+' Start. Command = '+command);
processCommand();
System.out.println(Thread.currentThread().getName()+' End.');
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public String toString(){
return this.command;
}
}

How do I test the completion of threads created under my testmethod in JUnit

I have a method createThreads which spawns few new threads. Each of the newly created thread does some work. If I invoke the method `createThreads' in junit, how can i ensure that all the newly spawned threads have also completed successfully.
I am currently calling as below
#Test
public void test() {
createThreads(); // Does not wait until the newly created threads also finish.
}
public void createThreads()
{
ExecutorService executorService = Executors
.newFixedThreadPool(numThreads);
for (int i = 0; i < numThreads; i++) {
executorService.execute(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I have completed execution " + Thread.currentThread().getName());
}
});
}
Note that I cannot modify createThreads
a bit odd but..
you can probably get all the runing threads
through Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
then filter it to identify the thread from the executor service.
then do a .join() on each of those threads.
as i said, a bit odd but it should fit your needs ...
try running this, you'll see that they are quite easy to identify :
public static void main(String[] args) {
int nb = 3;
ExecutorService executorService = Executors.newFixedThreadPool(nb);
for (int i = 0; i < nb; i++) {
executorService.execute(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I have completed execution " + Thread.currentThread().getName());
}
});
}
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread t : threadSet) {
System.out.println(t.getName());
}
}
sorry for a 2nd answer not possible to add such a long code in comment

Categories

Resources