Differences between tesing multi-thread in JUnit and Main function in Java - java

I tested a multi-thread program in JUnit and main function, source code as follows:
public class TestDaemon {
#Test
public void test() {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("hello");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// default false
thread.setDaemon(false);
thread.start();
}
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("hello");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// default false
thread.setDaemon(false);
thread.start();
}
}
It didn't print hello string in the JUnit test example.
In the main function example, it could print hello in the console, but when I set the thread.setDaemon(true), it also can't print hello.
I know this is related to Daemon thred and User thread, but I don't know how to explain it.

A daemon thread is a thread that does not prevent the JVM from exiting when the program finishes but the thread is still running. An example for a daemon thread is the garbage collection.
When you run your code from main it creates both beans, thus two threads - daemon and non-daemon. As long as non-daemon thread is running, your application won't exit. So it works.
It's different when run from JUnit. As soon as JUnit test method completes (and it completes immediately after the Spring context is up), JUnit assumes your tests are done. Thus it kills all your threads and basically the whole JVM.
Remember your Waitor1 bean spawns a background thread which JUnit doesn't care about. As soon as you leave #Test method JUnit will just stop everything.

We can analyze the source code of JUnit, part of junit.textui.TestRunner as follows:
public static final int SUCCESS_EXIT = 0;
public static final int FAILURE_EXIT = 1;
public static final int EXCEPTION_EXIT = 2;
...
public static void main(String args[]) {
TestRunner aTestRunner = new TestRunner();
try {
TestResult r = aTestRunner.start(args);
if (!r.wasSuccessful()) {
System.exit(FAILURE_EXIT);
}
System.exit(SUCCESS_EXIT);
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(EXCEPTION_EXIT);
}
}
/**
* Returns whether the entire test was successful or not.
*/
public synchronized boolean wasSuccessful() {
return failureCount() == 0 && errorCount() == 0;
}
/**
* Gets the number of detected failures.
*/
public synchronized int failureCount() {
return fFailures.size();
}
/**
* Gets the number of detected errors.
*/
public synchronized int errorCount() {
return fErrors.size();
}
In this source code, we can conclude that the TestRunner excutes the Unit Test method, no need to wait it finish their tasks, then calls System.exit() method, so that terminates the program. So, it couldn't print hello in the console.
In the main function, because the new thread is not daemon thread, the main program will wait it finishing their tasks, then teminates the program. So,hellostring could be seen in the console.

Related

Daemon thread with infinite loop not terminating

I have a simple test program (garage simulation) with several threads (Vehicle, MysteryVehicle, Observer objects) instantiated and started. Only the Observer object is a daemon thread running an infinite loop.
After all non-daemon threads terminate, Observer thread never does and the loop is executed infinitely (so this isn't some buffered output after the daemon thread really terminates - it does go on forever).
All of the non-daemon threads print something to the console just before exiting their run() methods, and it clearly shows all of them really terminated. I also didn't call join() on the daemon thread. When printing out all currently running threads, observer is listed as well, so my guess is that this daemon thread isn't terminating properly.
The complete code can be found on this commit.
Below you can see all threads created, started and where exactly is join() called.
Main.java
package garage;
import java.util.Set;
import garage.model.*;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Platform platform = new Platform();
Vehicle.platform = platform;
platform.print();
Vehicle[] vehicles = new Vehicle[30];
for (int i = 0; i < 30; i++) {
vehicles[i] = new Vehicle();
}
for (int i = 0; i < 30; i++) {
vehicles[i].start();
}
Observer observer = new Observer();
observer.platform = platform;
observer.start();
MysteryVehicle mysteryVehicle = new MysteryVehicle();
mysteryVehicle.start();
try {
mysteryVehicle.join();
} catch (Exception exception) {
exception.printStackTrace();
}
try {
for (int i = 0; i < 30; i++)
vehicles[i].join();
} catch (Exception exception) {
exception.printStackTrace();
}
System.out.println("before");
platform.print();
System.out.println("after");
synchronized (Platform.lock) {
System.out.println("END");
System.out.println(platform.flag); // checks whether wait() was called anytime
}
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread t : threads) {
System.out.println(t.getName());
}
}
public static void main(String[] args) {
launch(args);
}
}
Observer.java
package garage.model;
public class Observer extends Thread {
public Platform platform;
static int count = 0;
{
setName("observer");
setPriority(MIN_PRIORITY);
setDaemon(true);
}
#Override
public void run() {
while (true) {
synchronized (Platform.lock) {
try {
System.out.println(++count);
platform.print();
Platform.lock.wait(5000); // hack for when there is no meaningful loop condition
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
Platform.lock.notifyAll();
}
}
}
}
}
Vehicle run() method - relevant part
public void run() {
...
System.out.println("done");
}
MysteryVehicle run() method - relevant part
public void run() {
synchronized (Platform.lock) {
System.out.println("And the vehicle disappears!");
...
}
}
All of the relevant thread messages are printed out to the console.
done - 30 times, And the vehicle disappears!, before, after, END, true
This is the list of all of the running threads:
Attach Listener
main
Common-Cleaner
JavaFX Application Thread
Signal Dispatcher
Finalizer
InvokeLaterDispatcher
Reference Handler
QuantumRenderer-0
observer
Thread-2
JavaFX-Launcher
Since the program doesn't terminate and the print() function the run() method of observer calls is executed infinitely, what is it that prevents the daemon thread from terminating?
What am I missing here?
I suspect main() never returns, so the main thread (and perhaps some of those FX threads) are still running.
From the Application doc:
The launch method does not return until the application has exited,
either via a call to Platform.exit or all of the application windows
have been closed.
The posted code has no window to close nor is Platform.exit() invoked.
As far as I know, calling join on daemon thread is a bad idea.The idea behind using daemon thread is it will not halt JVM from exiting. What you can do is send an interrupt to that thread and call join after that.

Recursive calling of run method due to Thread.currentThread().run()

i am new to multithreading and trying to clear my basics.
public class SleepExample extends Thread {
private int counter = 0;
#Override
public void run() {
try {
counter++;
System.out.println("Value of counter "+counter);
System.out.println("Thread going in sleep "+Thread.currentThread().getName());
Thread.currentThread().run();
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("Thread out of sleep "+Thread.currentThread().getName());
}
public static void main(String[] args) {
new SleepExample().start();
new SleepExample().start();
Test test = new Test();
Thread t = new Thread(test);
t.start();
}
}
//another class implementing runnable
public class Test implements Runnable {
#Override
public void run() {
System.out.println("In Test runnable method");
}
}
When i run this code, my run method of SleepExample recursively call itself after below line
Thread.currentThread().run();
for thread belonging to SleepExample (Thread -0, Thread -1) and
it goes to run method of Test class for thread t.
I am unable to understand the usage of Thread.currentThread().run();
P.S. - I read its java doc and so i have implemented a runnable
I am unable to understand the usage of Thread.currentThread().run();
You are not supposed to call it directly. From Thread.start() You are supposed to use start() to call run() and that is it.
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
You are already running in the run() so you should only call this if you can say why you are doing it, even then it will look like a bug or be plain confusing and I would suggest you use a loop instead.
When i run this code, my run method of SleepExample recursively call itself after below line
You have a method calling itself, so you should expect that to happen. There is nothing special to Thread in this regard. It is like any other recursive call in a method.

How to test a method using sleep() with Java?

I have the following method and I am struggling to get 100% code coverage.
public final class SleepingHelper {
public static void sleepInMillis(Duration timeOfNextTry) {
try {
Thread.sleep(timeOfNextTry.toMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The question is how can I force Thread.sleep to throw an exception?
Edit: since it was marked as duplicate, I am still wondering what I would assert in the test ? The other question Is more generic.
You need to interrupt it from another thread. For example:
Thread t = new Thread() {
public void run () {
SleeperMillis.sleepInMillis(new Duration(10000000l));
}
}.start();
Thread.sleep(100); // let the other thread start
t.interrupt;
You don't need to actually interrupt the thread. You can use PowerMockito to mock the static method Thread.sleep()
#RunWith(PowerMockRunner.class)
#PrepareForTest(Thread.class)
public class TestClass {
#Test
public void testSleepInMillis() throws Exception {
PowerMockito.mockStatic(Thread.class);
PowerMockito.doThrow(new InterruptedException ()).when(Thread.class);
try {
SleepHelper.sleepInMillis(11);
fail("expected exception");
} catch (InterruptedException e) {
System.out.println("all good");
}
}
You don't test it, because you can't assert its results, and you can't assert it because Thread.sleep is not accurate or guaranteed to sleep for this duration of time, and the test results will differ from run to run.
Mocking is a better option here.
Btw, it is not just that your tests aren't predictable, your code that uses Thread.sleep in production is going to be unpredictable for the same reasons. Thread.sleep(some magic number goes here) usually indicates a badly written program.
I wouldn't bother testing it. 100% coverage is excessive. However, you could do it like this:
#Test
public void testException() throws Exception {
// Capture the system error stream, so that we can test that the expected exception is printed.
ByteArrayOutputStream capturedErrors = new ByteArrayOutputStream();
System.setErr(new PrintStream(capturedErrors));
// Create a new thread on which to run the candidate method.
Thread thread = new Thread() {
#Override
public void run() {
SleepingHelper.sleepInMillis(Duration.ofMillis(10));
}
};
// Start the second thread.
thread.start();
// Interrupt the second thread. (The candidate method hasn't finished yet. It takes 10 milliseconds to run.)
thread.interrupt();
// Wait for the thread to die (and write out the stack-trace).
thread.join();
// Test that the expected exception's stack trace was printed to the system error stream.
// The output should start with the exception's name.
String output = capturedErrors.toString();
int lengthOfExceptionName = "java.lang.InterruptedException".length();
assertEquals(output.substring(0, lengthOfExceptionName), "java.lang.InterruptedException");
}

Stopping a running process via GUI, in java

I have a GUI program that executes TestNG automation scripts. It's meant for users to easily configure some setting and launch the automation script that they want.
One thing I need to add is the ability to instantly stop the running TestNG process. Something like how in Eclipse, the 'Terminate' button will instantly stop whatever is running.
This is what the code that launches the TestNG tests looks like:
public class ScriptRunner implements Runnable {
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
As per the comment, the tng.run() can take several minutes to complete, and it's performing several things, opening/closing browser windows, etc.
How can I just instantly terminate the process, like you would when running an application from an IDE?
EDIT:
Per the comments, I'm attempting to use a ServiceExecutor and shutDownNow() The code is looking like this:
ExecutorService executorService = Executors.newFixedThreadPool(10);
public void runScript() {
executorService.execute(this);
}
//this method gets called when I click the "stop" button
public void stopRun() {
executorService.shutdownNow();
}
#Override
public void run() {
//same stuff as from earlier code
}
Spawn a child JVM process using ProcessBuilder or Runtime and you will be able to terminate that process when the user requests that the script stops running.
You can use ExecutorService to start test execution into one another thread. You can choose to have many thread in parrallel or juste one thread for all tests in sequence by choosing which executor service you need.
After that, start the execution of all tests in the same executor service instance by calling submit() method on it. You can stop the execution of all submitted runnables by calling shutdownNow() method.
It is important to use the same instance of ExecutorService, otherwise you start each test in a different thread and you will not enable to break the execution chain (or by calling shutdownNow() on all of them).
I was recently working on the executor framework. Here I have listed my problem
http://programtalk.com/java/executorservice-not-shutting-down/
Be careful if you are doing some IO operations the executor service may not shutdown immediately. If you see the below code stopThread is important because it tells your program that the thread has been asked to stop. And you can stop some iteration what you are doing.
I will modify your code like this:
public class MyClass {
private ExecutorService executorService;
private boolean stopThread = false;
public void start() {
// gives name to threads
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("thread-%d").build();
executorService = Executors.newSingleThreadExecutor(factory);
executorService.execute(new Runnable() {
#Override
public void run() {
try {
doTask();
} catch (Exception e) {
logger.error("indexing failed", e);
}
}
});
executorService.shutdown();
}
private void doTask() {
logger.info("start reindexing of my objects");
List<MyObjects> listOfMyObjects = new MyClass().getMyObjects();
for (MyObjects myObject : listOfMyObjects) {
if(stopThread){ // this is important to stop further indexing
return;
}
DbObject dbObjects = getDataFromDB();
// do some task
}
}
public void stop() {
this.stopThread = true;
if(executorService != null){
try {
// wait 1 second for closing all threads
executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
What about this,
add a volatile static boolean and make the thread code look like...
if(ScriptRunner.runThread){
//Do some stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do rest of the stuff here
}
Now you can add a button in your main GUI that simply sets the runThread to false so the thread will terminate nearly instant leaving all the leftover code untouched as you press the Stop button.
public class ScriptRunner implements Runnable {
volatile static Boolean runThread = true;
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
public void terminate(){
runThread = false;
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
How about a new Thread? You have to add an private Thread thread; in the gui and when ever you start
thread = new thread(){
#Override
public void run(){
//start process here
}
};
thread.start();
and to stop "terminate"
thread.stop();(depracted) or thread.setDeamon(true);
Everytime I have to stop a process by the gui I use this.
Hope I could help ;)
In your GUI somewhere you have something like
ScriptRunner scriptRunner = new ScriptRunner();
scriptRunner.runScript();
When you want to stop it call
scriptRunner.interrupt();
Change the code in ScriptRunner
private Thread testRun;
public void runScript() {
testRun = new Thread(this);
testRun.start();
}
public void interrupt() {
testRun.interrupt();
}
Save all created processes and kill them when your program ends:
public class ProcessFactory {
private static Set<Process> processes = new HashSet<>();
private static boolean isRunning = true;
public static synchronized Process createProcess(...) throws ... {
if (!isRunning)
throw ...
... // create your spawned process
processes.add(process);
return process;
}
public static synchronized void killAll() {
isRunning = false;
for (Process p : processes)
p.destroy();
processes.clear();
}
public static void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
void run() {
killAll();
}
});
}
}
This can be improved by adding a mechanism that removes already dead processes, but you get the general idea.

Future cancel(boolean b) method not working when used in GUI application

I have the following code:
public class Cancelling {
public static void main(String args[]) {
ToBeCancelled tbc = new ToBeCancelled();
ForkJoinPool pool = new ForkJoinPool(1);
Future<?> future = pool.submit(tbc);
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {}
future.cancel(true);
if (future.isCancelled())
System.out.println("The task has been cancelled");
}
}
With the ToBeCancelled class being:
public class ToBeCancelled implements Runnable {
public void run() {
try {
Thread.sleep(5000); // should throw exception here
} catch (Exception e) {
return; // should exit
}
System.out.println("I should never be able to print this");
}
}
The main thread should start, wait for 3 seconds, and then cancel the ToBeCancelled task by using future.cancel(true). It then should print The task has been cancelled, while the task never gets to print its message.
At least, this is what happens when I start it from console.
As I start it from a GUI application with a TextArea where the output is redirected to, that's not the case. The main method does print The task has been cancelled, but the task also prints I should never be able to print this.
This is driving me insane. From what I understand the task should receive its cancel command while on the Thread.sleep(5000) method, which would fire an exception that is consequently caught and makes the thread return. But it doesn't happen and yet the main thinks it has been cancelled. It's like the cancel method is completely ignored by the task.
I've tried everything I could think of, checking on the returned value of cancel, making the task wait longer, using Thread.currentThread().isInterrupted(), but nothing works.
I feel like I'm missing something really simple, but I just can't find what it is. Any idea?
In case anyone thinks it might be something on the GUI application, this is the method that starts the program:
public static void StartProgram(String name) {
try {
Method m = Class.forName(name).getDeclaredMethod("main",String[].class);
Object[] args = new Object[1];
String s[] = new String[2];
s[0] = tf1.getText();
s[1] = tf2.getText();
args[0] = s;
t = new Thread(new ProgramStarter(args, m));
t.start();
} catch (Exception e) {
e.printStackTrace();
}
}
With ProgramStarter being:
public class ProgramStarter implements Runnable {
private Object[] args;
private Method m;
public ProgramStarter(Object args[], Method m) {
this.args = args;
this.m = m;
}
public void run() {
try {
m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The problem is that your verification is wrong. You think that your code works when running from the console but in fact, it fails in all cases. When running from the console your main thread ends after the attempt to cancel the future and the JVM will terminate as there are only daemon threads left in the JVM. Due to the JVM termination you don’t notice that the cancellation did not work.
When adding a sleep at the end of your main method to delay the JVM termination you will notice that "I should never be able to print this" is printed when running from the console as well. So the only difference between GUI and console version is that the running Event Dispatch Thread prevents the JVM from terminating so you see that it doesn’t work.
The bottom line is: don’t use ForkJoinPool unless you have a reason for this.
Since you just want submit to a simple single-background-thread executor, you can create the executor using Executors.newFixedThreadPool(1). This has less unexpected behavior: it’s thread is non-daemon by default and it’s Future will cancel with interruption as expected.

Categories

Resources