I am using AssertThrows to test for an exception thrown in a thread. I know an exception is thrown since the exception message shows before the AssertionFail message.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(1);
SingleThread thread = new SingleThread();
pool.execute(thread);//Thread 1 (in real application there are several)
}
}
class SingleThread implements Runnable{
#Override
public void run() {
throw new NullPointerException();
}
}
class Testing{
#Test
public void SingleThreadTest() {
SingleThread testClass = new SingleThread();
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(testClass);
Assertions.assertThrows(NullPointerException.class, () -> executor.execute(testClass));
}
}
It appears that JUnit does not see the exception since it is not thrown on the main thread. Is it possible for JUnit detect the exception in this situation?
Related
I am reading the book Introducing Play Framework: Java Web Application Development (ISBN 978-1-4842-5645-9) and there is this example on Callable:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableClient {
/**
* #param args
*/
// Step1 : Create a Runnable
public static void main(String[] args) {
Callable callableTask = new CallableTask();
// Step 2: Configure Executor
// Uses FixedThreadPool executor
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(callableTask);
boolean listen = true;
while (listen) {
if (future.isDone()) {
String result;
try {
result = future.get();
listen = false;
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
executor.shutdown();
}
}
My question is, if the computation of the Future throws and exception, will the while loop run forever?
In my opinion, yes, it will loop forever.
First, if the Future computation throws an exception, then
future.isDone()
always evaluates to true. So we reach the inside of the if, where the stopping condition can be set. Still Ok.
Second, as per future documentation, when reaching line
result = future.get();
it will always throw ExecutionException because the computation threw an exception. This exception is caught in the try-catch block, without reaching the stopping condition precondition, which is
listen = false
Lastly, the above will create an endless cycle.
Is there any mistake in my assumptions or is the author of the example really wrong?
The program mentioned above cycles forever, if the callable throws an exception.
This is a code snippet with the callable that throws an exceptions. Executing compiled snippet loops forever.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableClient {
public static class CallableTask implements Callable<String> {
#Override
public String call() throws Exception {
throw new Exception();
}
}
public static void main(String[] args) {
Callable<String> callableTask = new CallableTask();
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(callableTask);
boolean listen = true;
while (listen) {
if (future.isDone()) {
String result;
try {
result = future.get();
listen = false;
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
executor.shutdown();
}
}
the main class:
package com.xxx.yyy;
public class Hello{
public static void main(String[] args){
A a = new A();
while(true){
try {
a.execute(1000);
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
class A:
package com.xxx.yyy;
public class A{
public void execute(int sleepTime) throws Exception {
System.out.println("sleep time is "+sleepTime);
}
}
btrace script:
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.str;
import static com.sun.btrace.BTraceUtils.strcat;
import static com.sun.btrace.BTraceUtils.timeMillis;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.ProbeClassName;
import com.sun.btrace.annotations.ProbeMethodName;
import com.sun.btrace.annotations.TLS;
#BTrace
public class BtraceTest{
#OnMethod(clazz="com.xxx.yyy.A",method="execute",location=#Location(Kind.RETURN))
public static void traceExecute(#ProbeClassName String name,#ProbeMethodName String method,int sleepTime){
println(strcat("the class name=>", name));
println(strcat("the class method=>", method));
println(strcat("the class method params=>", str(sleepTime)));
}
}
everything is right.
BUT: when I move the line Thread.sleep(1000) to class A's execute function, like this:
package com.xxx.yyy;
public class A{
public void execute(int sleepTime) throws Exception {
System.out.println("sleep time is "+sleepTime);
Thread.sleep(1000);
}
}
the NoSuchMethodError is thrown by Hello.
Exception in thread "main" java.lang.NoSuchMethodError: com.xxx.yyy.A.$btrace$BtraceTest$traceExecute(Ljava/lang/String;Ljava/lang/String;I)V
at com.xxx.yyy.A.execute(Unknown Source)
at com.xxx.yyy.Hello.main(Hello.java:8)
my environment is
java version "1.8.0_121"
BTrace v.1.3.9 (20170111)
anyone can explain why?thanks!
I think your class should implements Runnable or extends Thread. Then only you can use start, sleepand such similar methods in your program. Have a look at here to know how to implement thread methods.
Listed below is example code that I found for using the java.util.concurrent.ExecutorService. The main class includes a shutdown() method that calls the shutdown() method on the ExecutorService. What I do not understand from this example is when this method would be invoked.
Thanks.
package multithreadingexample;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MultithreadingExample {
ExecutorService executor = Executors.newFixedThreadPool(3);
public void start() throws IOException {
int i=0;
while (!executor.isShutdown())
executor.submit(new MyThread(i++));
}
public void shutdown() throws InterruptedException {
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);
executor.shutdownNow();
}
public static void main(String argv[]) throws Exception {
new MultithreadingExample().start();
}
}
class MyThread implements Runnable {
private final int i;
MyThread(int i) {
this.i = i;
}
#Override
public void run() {
System.out.println("I am in thread:"+i);
}
}
Why it is there:
To provide a way to shut down the ExecutorService to stop it from running tasks and to free the threads that it is using.
How it gets called:
You need to call it when you are done using the ExecutorService. In the example code you provided it is not called anywhere.
From the documentation:
The shutdown() method will allow previously submitted tasks to execute
before terminating, while the shutdownNow() method prevents waiting
tasks from starting and attempts to stop currently executing tasks.
Below is a unit test which uses ScheduledExecutorService to execute a scheduled runnable every second :
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
public class ConcurrentRequestSimulator {
private static final int NUMBER_REQUESTS = 4;
#Test
public void testGetToDoList() {
try {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
scheduler.scheduleAtFixedRate(new RequestThreadInvoker(), 0, 1, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
private final class RequestThreadInvoker implements Runnable {
public void run() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 1; i <= NUMBER_REQUESTS; i++) {
es.execute(new RequestThread());
}
es.shutdown();
while (!es.isTerminated()) {
}
}
}
private final class RequestThread implements Runnable {
public void run() {
try {
System.out.println("in RequestThread");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The line System.out.println("in RequestThread"); in RequestThread does not appear to be invoked as no output is displayed to console.
I think the issue is that since the test runs to completion, it causes the scheduler to stop scheduling? Can the test be updated so that scheduler is not terminated and RequestThreadInvoker is invoked repeatedly once per second ?
In RequestThreadInvoker I create a new instance of ExecutorService. Could this be causing the issue ?
Adding Thread.sleep(99000); to end of test causes test to wait 99 seconds which is enough time for test to run.
The code below checks the usage of ExecutorCompletionService from Java Concurrency framework (the IDE being used is Netbeans).
But the program doesn't terminate. Why?
Code:
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
public class TestFuture {
public static void main(String... args) throws InterruptedException, ExecutionException {
Executor ex = Executors.newCachedThreadPool();
CompletionService<Long> cs = new ExecutorCompletionService<Long>(ex);
cs.submit(new Worker());
cs.submit(new Worker());
cs.submit(new Worker());
for (int i = 0; i < 3; i++) {
long l = cs.take().get();
//utilize the result
System.out.println(l);
}
}
}
class Worker implements Callable {
#Override
public Long call() throws Exception {
//do some task and return back
return System.currentTimeMillis();
}
}
Threads in thread pool will keep running when main is finished. That's why JVM won't shut down. You need to either use daemon-threads, or shutdown the pool explicitly.
Here's an example:
ExecutorService ex = Executors.newCachedThreadPool();
// do all your submission work here
ex.shutdown();