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
I want to transfer objects (AssignmentListener) from one Java Server to 5 Java Clients.
Therefore I wrote a method to send out the message:
private void sendMessage(AssignmentListener listener, int[] subpartitionIndices){
boolean success = false;
int failCount = 0;
// retry for the case of failure
while(!success && failCount < 10) {
try {
// get the stored socket & stream if stored
if(listener.getSocket() == null) {
if (localMode) {
listener.setSocket(new Socket("localhost", listener.getPort()));
} else {
listener.setSocket(new Socket(listener.getIp(), listener.getPort()));
}
listener.setOutputStream(new ObjectOutputStream(listener.getSocket().getOutputStream()));
}
AssignmentListenerMessage assignmentListenerMessage = new AssignmentListenerMessage(subpartitionIndices);
System.out.println("Sending " + assignmentListenerMessage);
listener.getOutputStream().writeObject(assignmentListenerMessage);
listener.getOutputStream().flush();
success = true;
} catch (IOException se) {
se.printStackTrace();
System.err.println("Failed to forward " + Arrays.toString(subpartitionIndices) + " to " + listener);
failCount++;
}
}
}
On the client side, I have the following:
public void run() {
String mode = "remote";
if(localMode) mode = "local";
// we need to register this listener at at the OverpartitioningManager
if(register(isLocalRequest)) System.out.println("Registered AssignmentListenerServer for index "+subpartitionIndex+" at ForwardingServer - "+mode);
running = true;
while (running) {
try {
socket = serverSocket.accept();
// Pass the socket to the RequestHandler thread for processing
RequestHandler requestHandler = new RequestHandler( socket );
requestHandler.start();
} catch (SocketException se) {
se.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
class RequestHandler extends Thread {
private Socket socket;
RequestHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Received a connection");
// Get input and output streams
inStream = new ObjectInputStream(socket.getInputStream());
//outStream = new DataOutputStream(socket.getOutputStream());
AssignmentListenerMessage incomingMessage = null;
while(socket.isBound()) {
try {
incomingMessage = (AssignmentListenerMessage) inStream.readObject();
}catch (StreamCorruptedException sce){
System.out.println("Failed to read AssignmentMessage from Stream, but will try again... (no ack)");
sce.printStackTrace();
continue;
}
// do stuff with the message
}
// Close our connection
inStream.close();
socket.close();
System.out.println("Connection closed");
} catch (Exception e) {
e.printStackTrace();
}
}
}
This works multiple times, but at one point I get the following exception:
java.io.StreamCorruptedException: invalid type code: 00
Does anyone have an idea or any other performance improvement for what I'm doing?
Thanks.
I want to do following operation in ordered wise
1. Stop jetty server
2. Delete used resource from jetty
3. Restart jetty server.
I have done this above using shutdownhook in java as below :
<code>
Thread restartThread = new Thread(){
public void run(){
try {
sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String osName = System.getProperty("os.name");
logger.debug("OS name:" + osName);
if (osName != null
&& osName.toUpperCase().startsWith("WINDOWS")) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
List<String> cmdLine = new ArrayList<String>();
cmdLine.add("cmd.exe");
cmdLine.add("/C");
cmdLine.add("start");
cmdLine.add("\"\"");
cmdLine.add(getBaseDir() + File.separator + "restart.bat");
final ProcessBuilder pb = new ProcessBuilder(cmdLine);
Process process = pb.start();
if (process.exitValue() == 0) {
// after stopping server delete stores
deleteCertificates();
// restores files
restoreFiles(tmpdir, backupfilelist);
}
//p.waitFor();
} catch (IOException e) {
logger.error("Failed to restart:" + e.getMessage(), e);
}
}
});
System.exit(0);
} else {
try {
Runtime.getRuntime().exec("service appservice restart");
} catch (IOException e) {
logger.error("Failed to restart:" + e.getMessage(), e);
}
}
}
};
restartThread.start();
<code>
my concern is will it do it sequentially execution, otherwise application will fail to restore.
I'm really confused by this: some of my code is not working when i run my program normally in eclipse, but it does wok when i run through each step separately using the debug mode.
Code:
public void showConnectDialog() {
ConnectDialog connectDialog = new ConnectDialog();
connectDialog.setVisible(true);
//Until here, code runs
while(! connectDialog.getConnected()) {};
//The next line does only run in debug
JOptionPane.showMessageDialog(connectDialog, "Connected", "Connected", JOptionPane.INFORMATION_MESSAGE);
}
The connector (is started (as a thread) as soon as the user hits 'connect' in the dialog):
private class ServerConnector implements ActionListener, Runnable {
#Override
public void actionPerformed(ActionEvent e) {
if (! IP_field.getText().equals("")) {
if (! isConnecting) {
new Thread(new ServerConnector(), "ServerConnector").start();
}
}
else {
JOptionPane.showMessageDialog(dialog,
"Enter an IP address",
"Enter IP",
JOptionPane.WARNING_MESSAGE);
}
}
#Override
public void run() {
try {
setConnecting(true);
Socket socket = connect();
if (socket != null) {
ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream oIn = new ObjectInputStream(socket.getInputStream());
if (login(oOut, oIn)) {
isConnected = true;
setConnecting(false);
}
else {
socket.close();
}
setConnecting(false);
}
}
catch (RSPException e) {
e.printStackTrace();
System.exit(1);
}
catch (Exception e) {
//If an exception occurs, setConnecting() will be true. This
//not good, so it has to be set to false
e.printStackTrace();
setConnecting(false);
}
}
private boolean login(ObjectOutputStream oOut, ObjectInputStream oIn)
throws ClassNotFoundException, IOException, RSPException {
//Send login request action:
oOut.writeObject(new LoginAction(ActionSender.CLIENT, getID(),
getPassword()));
Object obj = oIn.readObject();
if (obj instanceof LoginActionResult) {
LoginActionResult result = (LoginActionResult) obj;
if (result.getResult() == LoginResults.SUCCES) {
return true;
}
else if (result.getResult() == LoginResults.FAIL_ON_ID) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.FAIL_ON_PASSWORD) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.SERVER_FULL) {
JOptionPane.showMessageDialog(dialog,
"Couldn't connect: \n" +
"Server is full",
"Failed to connect",
JOptionPane.WARNING_MESSAGE);
return false;
}
else {
return false;
}
}
else {
System.out.println(obj);
throw new RSPException("Server is not following the protocol.");
}
}
private void setConnecting(boolean connecting) {
if (connecting) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setEnabled(false);
}
});
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setText("Connecting...");
}
});
}
else {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setText("Connect");
}
});
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setEnabled(true);
}
});
}
isConnecting = connecting;
}
private String getAddressFromTextField() {
return IP_field.getText();
}
private InetAddress getInetAddress(String fullAddress) {
try {
if (fullAddress.contains(":")) {
String[] splitAddress = fullAddress.split(":");
return InetAddress.getByName(splitAddress[0]);
}
else {
return InetAddress.getByName(fullAddress);
}
}
catch (UnknownHostException e) {
return null;
}
}
private int getPort(String fullAddress) {
try {
String[] splittedAddress = fullAddress.split(":");
return Integer.valueOf(splittedAddress[1]);
}
catch (NumberFormatException ex) {
return -1;
}
catch (NullPointerException
| ArrayIndexOutOfBoundsException
| PatternSyntaxException ex) {
//Returning default port value: 25566, because no port was given
return 25566;
}
}
#SuppressWarnings("resource")
private Socket connect() {
Socket socket = null;
InetAddress address = null;
if ((address = getInetAddress(getAddressFromTextField())) == null) {
return null;
}
int port = getPort(getAddressFromTextField());
try {
socket = new Socket(address, port);
}
catch (ConnectException e ) {
Socket retrySocket = null;
if ((retrySocket = retryConnect(address, port)) == null) {
JOptionPane.showMessageDialog(dialog,
"Connection timed out",
"Failed to connect",
JOptionPane.ERROR_MESSAGE);
setConnecting(false);
}
else {
socket = retrySocket;
}
}
catch(IOException e) {
e.printStackTrace();
}
return socket;
}
private Socket retryConnect(InetAddress address, int port) {
Thread waitThread = new Thread(new Runnable() {
#Override
public void run() {
try {
//Will wait 15(000) (milli)seconds before stopping with
//trying to connect.
//One second (1000 millis) is for debugging and testing
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
waitThread.start();
while (waitThread.isAlive()) {
try {
return new Socket(address, port);
}
catch (ConnectException e) {
//Do nothing, will re-attempt to connect.
}
catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
private String getID() {
return ID_field.getText();
}
private String getPassword() {
if (getID().equals("master")) {
return "masterPassword";
}
else {
return new String(passwordField.getPassword());
}
}
}
getConnected() returns true as soon as it's connected to the server. The connector is running on a separate thread.
EDIT: I tried to put code in the getConnected() while block, and then it works. Why does it works then and not else?
I had the same Problem, but with some more specification. The code was working fine in 32bit but I had this issue in 64bit (I am using native library so I need to maintain both).
The solution I found is to add Thread.sleep() in the while loop. I don't know why it works, so your guess is as good as mine.
A better solution would probably to implement an Observer Pattern instead of having an infinite loop. But that would require some re-factoring.
Using Thread.sleep(), as the other answers have suggested, should solve the problem but it is not a very good approach. Instead, we should be using Thread.yield().
Why yield and not sleep?
Refer:
Difference between Thread.Sleep(0) and Thread.Yield() and Are Thread.sleep(0) and Thread.yield() statements equivalent?
Why this works?
When we just run the threads, the OS puts them to "idle" state and when it is expected to "wake-up", it does not. On the other hand, in debug mode, we have a controlled environment. The OS has little control over it as everything goes on step-by-step, slowly. If we run the debug a few times without any break-points, after a few successful runs, we should see the same effect.
I had a very similar problem with a "while" loop that wouldn't run and that loop was my main routine. How I got the loop to run was that the very first thing that was done in the loop was a sleep:
try
{Thread.sleep(0);}
catch (Exception e)
{e.printStackTrace();}
This was enough to get everything going.
I had same problem in UIAutomator with UiObject2 wait(Until.findObject(),20) .
Thread.yield() - works for me
My first attempt at writing a client for a php socket server and I'm running into a little trouble and I'm sort of being flooded with info!
With the server, we want an open connection, I want my client end to wait until it receives data before notifying the thread to start parsing the input-stream. Is this achievable without using a loop? I'd rather be able to call lock.notify().
I was also looking at NIO, is this a viable option for what I want?
Here's the code I have so far, but again, I'm just trying to avoid the for(;;) and maybe even queue the received messages as they will most likely just be JSON
Thread serverRecieve = new Thread(new Runnable() {
#Override
public void run() {
try {
for (;;) {
if (in != null) {
String line;
while ((line = in.readLine()) != null) {
sout(line);
}
} else {
sout("inputstream is null! Waiting for a second to test again");
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(WebManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (IOException ex) {
Logger.getLogger(WebManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
Thanks guys!
PS: I did look through A LOT of socket threads on here but decided it would be easier just to ask what I need.
I think you can use a while loop and put a condition using in != null as:
while(in == null){
//wait for a second before checking the in stream again
try {
sout("inputstream is null! Waiting for a second to test again");
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(WebManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
//now your in is available. Read the data and proceed
String line = null;
while ((line = in.readLine()) != null) {
sout(line);
}
The first while loop will terminate as soon in stream is available.
How about creating dedicated subtype of Runnable for reading from socket, like this:
class Reader implements Runnable {
private final Socket socket;
private volatile boolean stopped;
Reader(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
while (true) {
int in = socket.getInputStream().read();
// process in here
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (!stopped) socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stop() {
try {
stopped = true;
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Client {
private volatile Reader reader;
void start() {
reader = new Reader(new Socket(serverHost, serverPort));
Thread readerThread = new Thread(reader, "Reader-thread");
readerThread.start();
}
void stop() {
Reader reader = this.reader;
// reader.stop() will close socket making `run()` method finish because of IOException
// reader.socket is final, thus we have proper visibility of it's values across threads
if (reader != null) reader.stop();
}
}