I have implemented multithreading in my service layer and want to ensure I have dealt with all cases where the threads are properly handled. I don't want to end up with some kind of exception (such as RuntimeEx or InterruptedEx) which could leave my app in a bad state.
My code is below. Let me know if you can see any errors. Recommendations are most welcome. I'm using java 6.
public class MyRunnable implements Runnable {
private List<MyData> list;
private Person p;
public MyRunnable(List<MyData> list, Person p) {
this.list = list; // this list is passed in and cannot be null
this.p = p;
}
#Override
public void run() {
// before calling any of the services that gets data from the
// database, check if the thread has been interrupted
if (Thread.interrupted()) return;
List<TypeA> aList;
try {
aList = getTypeAFromDatabase1(p);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (Thread.interrupted()) return;
List<TypeB> bList;
try {
bList = getTypeBFromDatabase2(p);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (Thread.interrupted()) return;
List<TypeC> cList;
try {
cList = getTypeCFromSomeWebService(p);
} catch (Exception e) {
throw new RuntimeException(e);
}
MyData d = new MyData();
d.setPerson(p);
d.setTypeA(aList);
d.setTypeB(bList);
d.setTypeC(cList);
list.add(d);
}
}
Service that uses Runnable:
#JsonOperation
public static List<MyData> getMyData(MyParams params) throws Exception {
List<Person> persons = params.getPersonList();
try {
// use synchronized list since all threads will add to this list
List<MyData> retList = Collections.synchronizedList(new ArrayList<MyData>());
List<Thread> threads = new ArrayList<Thread>();
// For each person, start a new thread. It there are any runtime
// exceptions thrown by any one thread, it will be caught by the
// bigger try catch block. In case of runtime exception, we will
// return back to the client right away but the other threads
// are still processing
try {
for (Person p : persons) {
// create a thread per person and start it
Runnable task = new MyRunnable(retList, p);
Thread worker = new Thread(task);
threads.add(worker);
worker.start();
// remember the thread for later use
threads.add(worker);
}
for (Thread thread : threads) {
// wait for all threads (by waiting on one thread at a time)
thread.join(3000); //3 seconds between checking on this thread
}
} catch (RuntimeException e) {
log.error(e);
for (Thread thread : threads) {
// try and send an interrupt to all threads so that they
// don't fetch any more data from the database
thread.interrupt();
}
throw e;
}
return retList;
} catch (Exception e) {
log.error(e);
throw e;
}
}
In most situations it is easier to use tasks instead of threads. You start with an ExecutorService, which restricts the number of threads and is shared across all service operations:
// inject with IoC framework
ExecutorService executor = Executors.newFixedThreadPool(10);
You use the method invokeAll to execute a task for each person. If the tasks do not finish within the given period, then the remaining tasks will be automatically cancelled. In this case, an exception is thrown when invoking the get method of the corresponding future. That means there is no need for additional exception handling.
public List<MyData> getMyData(MyParams params) throws Exception {
List<Callable<MyData>> tasks = new ArrayList<>();
for (Person p : persons) {
tasks.add(new Callable<MyData>() { // use Lambda in Java 8
public MyData call() {
MyData d = new MyData();
d.setPerson(p);
d.setTypeA(getTypeAFromDatabase1(p));
d.setTypeB(getTypeBFromDatabase2(p));
d.setTypeC(getTypeCFromSomeWebService(p));
return d;
}
});
}
List<MyData> result = new ArrayList<>();
for (Future<MyData> future : executor.invokeAll(tasks, 3000, TimeUnit.MILLISECONDS)) {
result.add(future.get());
}
return result;
}
There is no need to check the interrupted state within the callable. If a blocking operation is called within one of the methods, the method will automatically abort execution with an InterruptedException or some other exception (if it is implemented correctly). It is also possible to set the interrupted state instead of throwing an exception. However, that makes less sense for methods with return values.
Related
This is my current implementation which handles different file read/save operations consecutively:
public void runThread(MyThreadImpl myThreadImpl) {
synchronized (this) {
this.myThreadImpl = myThreadImpl;
notify();
}
}
synchronized public void run() {
while (true)
try {
wait();
Global.myReentrantLock.lock();
try {
try {
myThreadImpl.call();
} catch (FileException e) {
// trace e
} catch (RuntimeException e) {
// trace e
} catch (Exception e) {
// trace e
}
} finally {
Global.myReentrantLock.unlock();
}
} catch (InterruptedException e) {
// trace e
} catch (Exception e) {
// trace e
}
}
I have a problem that I don't wait for thread result before performing another operation, and I've come to a case where that is necessary.
Since I'm using Java 8, I wanted to wrap this in a CompletableFuture. How can I do this with my current implementation?
You could do the following:
Instead of storing the next job to be done as a single reference (this.myThreadImpl) that is updated once the lock is free, you could use a queue.
When a new job is added, a new CompletableFuture is created, and a reference to it is returned to the caller.
Once the job is completed, the future is completed.
Updating your code, and assuming queue is a blocking queue of type Queue<Pair<CompletableFuture<Void>, MyThreadImpl>>, you would have:
/**
* #return a Future that will complete once the passed MyThreadImpl has been run.
*/
public CompletableFuture<Void> runThread(MyThreadImpl myThreadImpl) {
Pair<CompletableFuture<Void>, MyThreadImpl> p =
new Pair<>(new CompletableFuture<>(),myThreadImpl);
queue.add(p);
return p.left;
}
public void run() {
while (true) {
try {
Pair<CompletableFuture<MyThreadImpl>, MyThreadImpl> p =
queue.take(); // will block until a job is added
try {
p.right.call();
p.left.complete(null); // Future<Void> can only be completed with null. Alternatively, it could be completed with a relevant result.
} catch (Exception e) {
p.left.completeExceptionally(e);
}
} catch (InterruptedException e) {
// trace e
}
}
}
Here, Pair just needs to be a pair-like pojo. (It could be apache commons's ImmutablePair, for example.)
Blocking queues are generally useful when stuff needs to be processed: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html
Also, have you looked at ExecutorService? You could use one that is based on a single thread to execute jobs in a serial way: it's submit(Callable<> task) method is quite like runThread() defined above, as it returns a Future<Void> that will tell you when the task is done.
If any of the submitted thread is throwing exception its not returning the exception.
I want to write a piece of code for my project where in if any of the thread execution is failed it should throw the exception there & it should stop all the running & scheduled threads.
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new MyObject());
executorService.submit(t);
}
I wrote MyObject like this..,
public class MyObject implements Runnable {
public void run() {
throw new NullPointerException("Sample NullPointerException");
}
}
Is this the correct implementation for my goal...?????
i want to achieve that goal please give me some pointers.
Thanks In Advance....!!
Here is something you can consider about. Here I am using CallableTask instead of Thread.
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
Set<Future<Void>> futureSet = new HashSet<Future<Void>>();
for (int i = 0; i < 9; i++) {
CallableTask1 task = new CallableTask1();
futureSet.add(executorService.submit(task));
}
CallableTask2 task2 = new CallableTask2();
futureSet.add(executorService.submit(task2));
boolean flag = false;
for (Future<Void> future : futureSet ) {
try {
future.get();
} catch (InterruptedException e) {
System.out.println("Interrupted");
} catch (ExecutionException e) {
System.out.println("Exception thrown from the thread");
flag = true;
break;
}
}
if(flag) {
for (Future<Void> future : futureSet) {
future.cancel(true);
}
}
}
Here I am using two classes to demonstrate this is working. When one task throw an exception the forever running task is also stop running.
class CallableTask1 implements Callable<Void> {
#Override
public Void call() throws Exception {
throw new NullPointerException("Sample NullPointerException");
}
}
class CallableTask2 implements Callable<Void> {
#Override
public Void call() throws Exception {
while (true){
System.out.println("THIS IS RUNNING");
Thread.sleep(5000);
}
}
}
But this has it's own limitations. This code will wait for it's turn to throw an exception because of "future.get()" executed sequentially.
Best case : Throw an exception in first future.get() and other tasks will be cancelled.
Worst case : Throw an exception in the last future.get() and by the time throw an exception all other tasks done with execution.
Optimizing : Identify the tasks that can throw an exception and wait for those tasks only to cancel all the other tasks.
If your run methods has while in it then best way share a flag and break on it. Check this answer for more information.
I'm using this code to divide up a few hundred tasks between different CPU cores.
final List<Throwable> errors = Collections.synchronizedList(Lists.<Throwable>newArrayList());
final ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (...) {
pool.execute(new Runnable() { #Override public void run() {
try {
// TASK HERE
} catch (Throwable e) {
errors.add(e);
}
}});
}
pool.shutdown();
try {
pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely"
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!errors.isEmpty()) throw Exceptions.wrap(errors.get(0)); // TODO multi-exception
It works, but it's not nice.
There is no version of awaitTermination without timeout, which is what I want.
I need to do my own error collecting.
What is the proper/common way to do this?
The point of a thread pool is to reuse threads. You should create it on application startup, outside of your code that creates tasks, and inject it. There is no need to shut down the pool after adding tasks. You do that when your application is shutting down.
To run a collection of tasks, use ExecutorService.invokeAll. To get the results afterwards, call get on each of the returned Futures. It will rethrow any exception that the task threw, so you can collect it afterwards.
You can use a future to do the error handling:
final List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < 5; i++) {
futures.add(pool.submit(new Runnable() { #Override public void run() {
// TASK HERE
}}));
}
for (Future f : futures) {
try {
f.get();
} catch (ExecutionException e) {
//something bad happened in your runnable
}
}
//when you are done with the executor
pool.shutdown();
try {
pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely"
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
I think you need to submit each Runnable, get a Future back, and then call get() on each Future.
When you call get(), you'll either get the result of the Runnable, or the exception that it encountered.
Good Day,
I am having concurrency problems with a LinkedList in Java. I have an Object type called "Connection" which has as a member variable LinkedList of "MessageHandlers" called "listeners". I then have two different threads, one modifying and one iterating over the same LinkedList.
I've seen many many other StackOverflow questions that suggest to use the sychronized block of code, but that doesn't appear to be helping it all. I've also try creating the LinkedList as a concurrent linked list, but I am still receiving the
Exception in thread "Thread-1" java.util.ConcurrentModificationException
exception. Does anyone have any other suggestions to try? Here are some snipbits of my code...
public synchronized Object ReadObject() throws java.io.IOException
{
Object obj = null;
try
{
obj = input.readObject();
synchronized(listeners)
{
Iterator<MessageHandler> i = listeners.iterator();
while(i.hasNext())
{
i.next().MessageReceived(obj, this);
}
}
}
catch (IOException e)
{
e.printStackTrace();
throw e;
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
The above code is inside my connection object. It gets called from a function that has a socket's ObjectInputStream reading data from the socket."input" is an instance of ObjectInputStream.
public void addNewLoggedInUser(User user) throws Exception
{
for(User u:loggedInUsers)
{
if(u == user)
{
throw new Exception("That user is already logged in");
}
}
//Add the new users
loggedInUsers.add(user);
synchronized(user.getConnection().getListeners())
{
user.getConnection().getListeners().add(this);
}
this.SendGameStatusUpdateToAllLoggedinPlayers();
}
I then call the method user.getConnection().getListeners().add(this) and thus am getting the exception.
public Connection()
{
//Initialize the variables to NULL
socket = null;
output = null;
input = null;
receiveThread = null;
runReceiveThread = false;
listeners = Collections.synchronizedList(new LinkedList<MessageHandler>());
//Handle the ID counter. Now we have a unique ID for every connection that comes in
connectionID = counterID;
counterID = counterID + 1;
}
This is the constructor for the connection class. Notice he Collections.synchronizedList
Any ideas? Thank you very much for your help!
java.util.ConcurrentModificationException isn't really a threading issue. It is cause by modification of a list locked by it's iterator. I think you are calling addNewLoggedInUser() from MessageReceived(). This would cause the concurrent modification exception since the calling function already has iterator lock on the linkedlist.
Go through BlockingQueue javadoc. It mentions a simple scenario as well that fits your requirements i.e.
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
The synchronized blocks look like they should work. I would expect that there is activity in methods called from within the ReadObject synchronized block which modify the list. Do any of your MessageHandlers call or chain to a call to addNewLoggedInUser (or any other method that might update the listener list)?
If so, the thread would already have the monitor grabbed by the ReadObject synchronized block, and would be able to enter the block in addNewLoggedInUser.
I have the following code snippet that basically scans through the list of task that needs to be executed and each task is then given to the executor for execution.
The JobExecutor in turn creates another executor (for doing db stuff...reading and writing data to queue) and completes the task.
JobExecutor returns a Future<Boolean> for the tasks submitted. When one of the task fails, I want to gracefully interrupt all the threads and shutdown the executor by catching all the exceptions. What changes do I need to do?
public class DataMovingClass {
private static final AtomicInteger uniqueId = new AtomicInteger(0);
private static final ThreadLocal<Integer> uniqueNumber = new IDGenerator();
ThreadPoolExecutor threadPoolExecutor = null ;
private List<Source> sources = new ArrayList<Source>();
private static class IDGenerator extends ThreadLocal<Integer> {
#Override
public Integer get() {
return uniqueId.incrementAndGet();
}
}
public void init(){
// load sources list
}
public boolean execute() {
boolean succcess = true ;
threadPoolExecutor = new ThreadPoolExecutor(10,10,
10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1024),
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("DataMigration-" + uniqueNumber.get());
return t;
}// End method
}, new ThreadPoolExecutor.CallerRunsPolicy());
List<Future<Boolean>> result = new ArrayList<Future<Boolean>>();
for (Source source : sources) {
result.add(threadPoolExecutor.submit(new JobExecutor(source)));
}
for (Future<Boolean> jobDone : result) {
try {
if (!jobDone.get(100000, TimeUnit.SECONDS) && success) {
// in case of successful DbWriterClass, we don't need to change
// it.
success = false;
}
} catch (Exception ex) {
// handle exceptions
}
}
}
public class JobExecutor implements Callable<Boolean> {
private ThreadPoolExecutor threadPoolExecutor ;
Source jobSource ;
public SourceJobExecutor(Source source) {
this.jobSource = source;
threadPoolExecutor = new ThreadPoolExecutor(10,10,10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1024),
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("Job Executor-" + uniqueNumber.get());
return t;
}// End method
}, new ThreadPoolExecutor.CallerRunsPolicy());
}
public Boolean call() throws Exception {
boolean status = true ;
System.out.println("Starting Job = " + jobSource.getName());
try {
// do the specified task ;
}catch (InterruptedException intrEx) {
logger.warn("InterruptedException", intrEx);
status = false ;
} catch(Exception e) {
logger.fatal("Exception occurred while executing task "+jobSource.getName(),e);
status = false ;
}
System.out.println("Ending Job = " + jobSource.getName());
return status ;
}
}
}
When you submit a task to the executor, it returns you a FutureTask instance.
FutureTask.get() will re-throw any exception thrown by the task as an ExecutorException.
So when you iterate through the List<Future> and call get on each, catch ExecutorException and invoke an orderly shutdown.
Since you are submitting tasks to ThreadPoolExecutor, the exceptions are getting swallowed by FutureTask.
Have a look at this code
**Inside FutureTask$Sync**
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
protected void setException(Throwable t) {
sync.innerSetException(t);
}
From above code, it is clear that setException method catching Throwable. Due to this reason, FutureTask is swallowing all exceptions if you use "submit()" method on ThreadPoolExecutor
As per java documentation, you can extend afterExecute() method in ThreadPoolExecutor
protected void afterExecute(Runnable r,
Throwable t)
Sample code as per documentation:
class ExtendedExecutor extends ThreadPoolExecutor {
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
System.out.println(t);
}
}
You can catch Exceptions in three ways
Future.get() as suggested in accepted answer
wrap entire run() or call() method in try{}catch{}Exceptoion{} blocks
override afterExecute of ThreadPoolExecutor method as shown above
To gracefully interrupt other Threads, have a look at below SE question:
How to stop next thread from running in a ScheduledThreadPoolExecutor
How to forcefully shutdown java ExecutorService
Subclass ThreadPoolExecutor and override its protected afterExecute (Runnable r, Throwable t) method.
If you're creating a thread pool via the java.util.concurrent.Executors convenience class (which you're not), take at look at its source to see how it's invoking ThreadPoolExecutor.