How to make main thread wait to complete UncaughtExceptionHandler execution - java

I have the following mutlithreaded code. I want the LatchCode.doStuff() to wait until UncaughtExceptionHandler handler completes it work, but it wasn't. How could I make the main thread to wait for it. I need to propagate the exception to parent for some project requirement to log the error into DB (should happen at the end of processing). Following is the piece of code.
public class LatchExceptionTest {
public static void main(String[] args) {
LatchCode l = new LatchCode();
Cont c = new Cont();
try {
l.doStuff(c);
System.out.println("Main Thread - work completed");
if(!c.err.isEmpty())
throw new Exception(c.err.toString());
} catch (Exception e) {
System.out.println("trace printing start");
System.out.println(c.err.toString()); // log errors to DB
System.out.println("trace printing edn");
}
}
}
class LatchCode {
public void doStuff(final Cont cont) throws RuntimeException, InterruptedException {
System.out.println("Intermediate class start");
try {
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread th, Throwable ex) {
cont.err.add(ex.getMessage());
}
};
Thread aggregatorThread = new Thread(() -> {
try {
if(cont.err.size() > 0)
return;
System.out.println("AGGREGATOR thread START");
Thread.sleep(3000);
System.out.println("AGGREGATOR thread END");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
CyclicBarrier barrier = new CyclicBarrier(2, aggregatorThread);
AA a = new AA();
BB b = new BB();
CountDownLatch latch = new CountDownLatch(2);
Thread one = new Thread(() -> {
try {
a.doSomething();
} catch (Exception e) {
System.out.println("Exception in 1");
//Thread.currentThread().interrupt();
throw new RuntimeException(e.toString());
} finally {
try {
barrier.await();
} catch (Exception e) {
System.out.println("Exception in 1 finallt");
throw new RuntimeException(e.toString());
} finally {
latch.countDown();
}
}
});
Thread two = new Thread(() -> {
try {
b.doSomething();
} catch (Exception e) {
System.out.println("Exception in 2");
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} finally {
try {
barrier.await();
} catch (Exception e) {
System.out.println("Exception in 2 finallt");
throw new RuntimeException(e);
} finally {
latch.countDown();
}
}
});
one.start();
two.start();
one.setUncaughtExceptionHandler(h);
two.setUncaughtExceptionHandler(h);
latch.await();
} catch (Exception e) {
System.out.println("Exception in caller");
throw new RuntimeException(e);
} finally {
System.out.println("Intermediate class end");
}
}
}
class AA {
public void doSomething() throws Exception {
try {
System.out.println("1 start");
Thread.sleep(1);
throw new Exception("In AA");
} catch (Exception e) {
System.out.println("Exception in AA");
throw new Exception(e.toString());
}
}
}
class BB {
public void doSomething() throws Exception {
try {
System.out.println("2 start");
Thread.sleep(1);
} catch (Exception e) {
System.out.println("Exception in BB");
}
System.out.println("2 end");
}
}
class Cont {
ConcurrentLinkedQueue<String> err = new ConcurrentLinkedQueue<String>();
}
If AA.doStuff() and BB.doStuff() has loger sleeps, then I could Cont.err is not empty and getting into catch block. But whne sleep time is negligible like 1 ms, then if block in main() failed and program is executing as if there is no exception.
So I need calling thread to wait for UncaughtExceptionHandler completion. Could some one help on this.
Thanks in advance

After making exhaustive search, found the following page. Go through the details on how things work in UEH.
https://bugs.openjdk.java.net/browse/JDK-8153487
Excerpt from the above thread for short answer:
There is no guarantee that UncaughtExceptionHandlers have run before awaitTermination returns.
It is a pool thread that sets the state to TERMINATED, so it cannot wait for all pool threads to terminate!
It seems unlikely we can make this better. It seems that relying on the UEH in this way is a poor design

Related

Thread.join() not behaving as expected

I'm pretty new to Multithreading in java but am totally stumped about why this isn't behaving as I want it to.
I have a Producer-Consumer wherein I have
private void produceConsume() {
try {
Thread producer = new Thread(new Runnable() {
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
completedProduce = true;
}
}
private void produce() throws InterruptedException {
synchronized (this) {
while (queue.size() == capacity) {
wait();
}
try(InputStream is = new FileInputStream(file)) {
queue.add("hello");
} catch (IOException e) {
LOG.error("Error doing stream stuff: " + e.getMessage(), e);
}
notify();
}
}
});
producer.start();
List<Thread> consumers = new ArrayList<>();
for (int i = 0; i < noOfThreads; i++) {
Thread consumer = new Thread(new Runnable() {
#Override
public void run() {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void consume() throws InterruptedException {
while (queue.size() > 0 || !completedProduce) {
synchronized (this) {
while (queue.size() == 0 && !completedProduce) {
wait();
}
String s = queue.poll();
System.out.println(s);
}
notify();
}
}
}
});
consumer.start();
consumers.add(consumer);
}
for (Thread t : consumers) {
t.join();
}
producer.join();
} catch (Exception e) {
LOG.error("InterruptedException e: " + e.getMessage(), e);
} finally {
LOG.info("We are done with this file!");
}
}
Now, I've noticed that all functionality changes based on where I put my producer.join() statement. For example, if I put producer.join() right after producer.start() then everything works - but the number of threads has no impact on runtime. This makes sense as I'm slowed down drastically by how long it takes to produce and so the longest task wins out.
However, if I put producer.join() where it is in the example provided (I do the join when I do the join for the consumers) then everything just stops running before the producer actually finishes. As in, the program stalls after the first thing is consumed, waiting for something, but the thread never dies.
How do I make it so that things run correctly and nothing stalls waiting for another process to finish?
Thanks in advance,

throw exception from java task does not work

I am trying to throw an exception inside a task which is run on a separate thread. Then I want to catch the exception on the calling thread. See my trial below:
When I run the code now it hangs at the line with "throws new RuntimeException.."
Task calcTask = createCalcTask();
ExecutorService executor = Executors.newFixedThreadPool(1);
Future future = executor.submit(calcTask);
try {
future.get();
} catch (ExecutionException ex) {
ex.getCause().printStackTrace();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
public Task<Object> createCalcTask() {
return new Task<Object>() {
#Override
protected Object call() throws Exception {
throw new RuntimeException("testE");
}
};
}
try this....
line throwing exception should be inside try block
try {
Future future = executor.submit(calcTask); //
future.get();
} catch (ExecutionException ex) {
ex.printStackTrace();
}

Java thread exit without warning

my java thread exit with any warning. I have no idea why the thread exit. I can't find it in jstack. And it seems the log code hadn't run. My code below:
private class WorkThread extends Thread {
public WorkThread() {
super("work-thread");
setDaemon(false);
}
#Override
public void run() {
logger.info("start running thread work-tracker");
try {
while (!interrupted()) {
try {
// do something
} catch (Throwable e) {
logger.error("ignore all exception", e);
}
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
} finally {
logger.error("work thread exit interrupted status: {}", interrupted());
}
}
}
I cannot find the log "work thread exit interrupted status" and anything about "work-thread" in the jstack log. any suggestion?
private class WorkThread extends Thread {
public WorkThread() {
super("work-thread");
setDaemon(false);
}
#Override
public void run() {
logger.error("start running thread work-tracker");
try {
while (!interrupted()) {
try {
// do something
} catch (Throwable e) {
logger.error("ignore all exception");
}
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
}
Thread.currentThread().interrupt();
}
} finally {
logger.error("work thread exit interrupted status: {}" +interrupted());
}
}
}

How to keep a thread alive forever until JVM is killed?

I have a thread which i wanted to run always until the JVM is stopped. What is the best way to do that ?
public void run() {
String event = sc.nextLine();
try {
queue.put(event); // thread will block here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Just adding an infinite loop should do the trick
public void run() {
while(true){
String event = sc.nextLine();
try {
queue.put(event); // thread will block here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
while (true) { runBody(); }
Add exception handling if necessary.

Apache Commons Net FTPClient abort file store

I'm developing an applet to allow FTP upload from a webapp...
The send operation is working fine, but I'd like to able to cancel a file storing in progress.
I'm not very fluent with threads. My first attempt was to call ftp.abort() in the cancel thread, but the abort method was only called when the storeFile method finished, like if the send thread was locking the ftp object.
So I changed the code to interrupt the send thread and check it in the copy stream listener. The file storing stops as expected, but ftp.abort() call hangs the application, it never complete.
Any ideas?
Thanks,
Philip
Send operation:
botaoEnviar.setEnabled(false);
botaoCancelar.setEnabled(true);
textField.requestFocus();
threadEnvio = new Thread(new Runnable()
{
#Override
public void run()
{
FileInputStream fis = null;
try
{
if(arquivoSelecionado == null)
{
throw new IllegalArgumentException("Arquivo deve ser informado");
}
try
{
ftp = new FTPClient();
ftp.connect("192.168.1.243");
}
catch(Exception e)
{
throw new FtpConnectionException("Não foi possível conectar no servidor FTP", e);
}
if(!ftp.login("c001", "0AJF2J36"))
{
throw new IllegalArgumentException("Não foi possível autenticar no servidor FTP");
}
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.setCopyStreamListener(new CopyStreamAdapter()
{
#Override
public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize)
{
if(threadEnvio.isInterrupted())
{
try
{
ftp.abort();
}
catch(IOException ex)
{
handleException(ex);
}
}
else
{
int percent = (int) (totalBytesTransferred * 100 / arquivoSelecionado.length());
progressBar.setValue(percent);
}
}
});
fis = new FileInputStream(arquivoSelecionado);
if(ftp.storeFile(arquivoSelecionado.getName(), fis))
{
JOptionPane.showMessageDialog(null, "Arquivo enviado com suceso");
}
else
{
JOptionPane.showMessageDialog(null, "Não foi possível enviar o arquivo", "Erro", JOptionPane.ERROR_MESSAGE);
}
ftp.logout();
}
catch(Exception e)
{
handleException(e);
}
finally
{
if(fis != null)
{
try
{
fis.close();
}
catch(IOException ex)
{
handleException(ex);
}
}
if(ftp != null)
{
try
{
ftp.disconnect();
}
catch(IOException ex)
{
handleException(ex);
}
}
progressBar.setValue(0);
botaoEnviar.setEnabled(true);
botaoCancelar.setEnabled(false);
}
}
});
threadEnvio.start();
Cancel operation:
botaoCancelar.setEnabled(false);
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
threadEnvio.interrupt();
}
catch(Exception ex)
{
handleException(ex);
}
finally
{
botaoCancelar.setEnabled(true);
}
}
}).start();
interrupting a thread like this is not correct, it causes your thread to wait for some seconds at exactly which line that compiler is reading in your thread
the only way that you can abort your ftp upload is to make the thread sleep for some time
then abort your upload and wait for the thread to complete itself
see this :
try {
try {
Thread.currentThread();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
mFTP.abort();
} catch (IOException e) {
e.printStackTrace();
}
} catch (NetworkOnMainThreadException e) {
e.printStackTrace();
}

Categories