Issue with java boolean - java

I'm attempting to create a chat client, I'm returning a message from the javaSpace, Then setting newMessage = true; So the client can see that there is a new message that needs to be read.
public void notify(RemoteEvent ev)
{
try
{
messageRead = false;
QueueItem qiTemplate = new QueueItem();
newMessage = (QueueItem)space.take(qiTemplate,null,Long.MAX_VALUE);
System.out.println(newMessage.getSender().getName()+ ": " + newMessage.getContent());
}
catch (Exception e)
{
e.printStackTrace();
}
}
Then for the client,
while(true)
{
try
{
boolean temp = _manager.messageRead;
//System.out.println(temp);
if(!temp)
{
QueueItem nextJob = _manager.newMessage;
String nextJobNumber = nextJob.getSender().getName();
String nextJobName = nextJob.getContent();
System.out.println(nextJob.getSender().getName()+ ": " + nextJob.getContent());
jobList.append( nextJobNumber + " : " + nextJobName + "\n" );
_manager.messageRead = true;
}
} catch ( Exception e)
{
e.printStackTrace();
}
}
That right now will ALWAYS return _messager.messageRead to be true, even though I've just set it too false. If I uncomment //System.out.println(temp); the boolean will then for some reason be updated and it will equal what its meant too.
I've never come across this error before and its extremely strange to me, So I'm hoping someone can help.

You don't seem to have synchronized accesses to your boolean flag messageRead. println happens to do that for you hence what you observe.
You could probably fix your issue by decalring the flag volatile:
private volatile boolean messageRead;
That will ensure that changes you make in one thread are visible from another thread without needing to synchronize your code.

Related

Java RMI odd/inconsistent Activatable.register behavior - UnknownGroupException

Trying to use RMI and having odd issue.
The code below I have snipped the catches. There are no exceptions in them - the code progress properly until:
reportServerRemote = Activatable.register(_desc);
When I run the code below THE FIRST TIME, I get
Exception: java.rmi.activation.UnknownGroupException: group unknown
on the call: reportServerRemote = Activatable.register(_desc);
Note that I have requested and set the _groupID.
When I run it the second time, it works. I thought it might be some kind of timing issue, and have add delays and retries at various spots, but to no effect.
ActivationSystem _activationSystem = null;
try {
String _lookMeUp = "//:" + RMID_ACTIVATION_SYSTEM_PORT + "/java.rmi.activation.ActivationSystem";
_activationSystem =
(ActivationSystem) Naming.lookup(_lookMeUp);
ActivationGroup.setSystem(_activationSystem);
ActivationGroupDesc _groupDesc = new ActivationGroupDesc(null, null);
ActivationGroupID _groupID = null;
try {
_groupID = _activationSystem.registerGroup(_groupDesc);
ActivationDesc _desc = null;
try {
_desc = new ActivationDesc(_groupID, ReportServer.class.getName(),
null,
new MarshalledObject(LicenseUtil.loadSerialAndLicense()));
reportServerRemote = Activatable.register(_desc);
Exception: java.rmi.activation.UnknownGroupException: group unknown
I added a looping check after the initial registerGroup call. If it failed I tried again. It always seems to work on the 2nd try, but I left at 10 tries - just in case.
ActivationGroupID _groupID = null;
try {
_groupID = _activationSystem.registerGroup(_groupDesc);
} catch (Exception pE) {
pE.printStackTrace();
logger.error("Unable to determine groupID for group description \"" + _groupDesc + "\"", pE);
throw new Exception("Got exception while attempting to obtain group id. Exception: " + pE);
}
/*
* Sometimes it does not work the first time. Keep trying.
*/
boolean _needToRegisterGroup = true;
for ( int i = 0; _needToRegisterGroup && i< 10; i++) {
_needToRegisterGroup = false;
try {
// See if it's there
ActivationGroupDesc _t = _activationSystem.getActivationGroupDesc(_groupID);
} catch (Exception e) {
// Try again
_groupID = _activationSystem.registerGroup(_groupDesc);
// Wait a bit before checking
try {
Thread.sleep(5000);
} catch (InterruptedException pIE) {
}
_needToRegisterGroup = true;
}
}
if ( _needToRegisterGroup ) {
throw new Exception("Never able to RegisterGroup with RMID.");
}

How to avoid Stack Overflow errors in infinitely recursive method?

I know there are tons of posts about stack overflow errors and i understand why my specific one is happening, my question is basically how to move away from recursion in this specific case. I have a class which establishes and maintains a client connection (for HL7 messaging specifically but it's essentially a glorified client connection) to another system which hosts corresponding server connections. This class' constructor starts a new thread and runs the following method :
#Override
public void connect()
{
try
{
setStatus("Connecting");
connection = context.newClient(intfc.getIp(), port, false);
connected = true;
setStatus("Connected");
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully connected " + connectionType + " client connection to "
+ intfc.getName() + "(" + intfc.getIp() + ") on port " + port);
monitor();
}
catch (HL7Exception ex)
{
connected = false;
setStatus("Disconnected");
try
{
TimeUnit.SECONDS.sleep(connectionRetryIntervalInSeconds);
connect();
}
catch (InterruptedException ex2)
{}
}
}
Upon successfully connecting with the server, the monitor method simply checks, in yet another thread, if the connection is still up at a given interval. If it goes down, the monitoring thread is interrupted and the connect() method is called again.
I did not anticipate this at first but you can quickly see why the connect() method is causing stack overflow errors after several days running. I'm struggling to think of a way to get the same functionality to work without the connect method calling itself again every time the connection fails.
Any suggestions would be appreciated.
Thanks!
Typically you'd use a Stack object to emulate recursion when required.
However, in your case, why are you using recursion at all? A while loop fits the purpose.
while(true /**or some relevant condition**/){
try{ //try to connect
....
catch(HL7Exception ex){
//sleep
}
}
I'm not sure of the purpose of your application, but there are may be better methods than sleeping. You could use a ScheduledExecutorService, but if it's a single threaded program with one purpose it's probably unnecessary.
When I had to deal with this issue in c# I used a Stack, and added new classes to it, instead of using recursion. Then a second loop would check to see if there were any objects in the stack that needed dealing with. That avoided stack overflow when I would have had huge amounts of recursion otherwise. Is there a similar Stack collection in Java?
Why are you calling the monitor() method in the first place? You mention that it is launched in a separate thread, then can't you just launch it in a new thread when the application comes up? Then there won't be a recursive call.
I changed my code to an iterative approach as suggested, works beautifully!
#Override
public void initThread()
{
initConnectionEntity();
mainThread = new Thread()
{
#Override
public void run()
{
while (running)
{
if (!connected)
{
try
{
connect();
}
catch (HL7Exception ex)
{
connected = false;
setStatus("Disconnected");
try
{
TimeUnit.SECONDS.sleep(connectionRetryIntervalInSeconds);
}
catch (InterruptedException ex2)
{}
}
}
try
{
TimeUnit.MILLISECONDS.sleep(500);
}
catch (InterruptedException ex2)
{}
}
}
};
mainThread.setName(intfc.getName() + " " + connectionType + " Main Thread");
mainThread.start();
}
#Override
public void connect() throws HL7Exception
{
setStatus("Connecting");
connection = context.newClient(intfc.getIp(), port, false);
connected = true;
setStatus("Connected");
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully connected " + connectionType + " client connection to "
+ intfc.getName() + "(" + intfc.getIp() + ") on port " + port);
monitor();
}
private void monitor()
{
monitoringThread = new Thread()
{
#Override
public void run()
{
try
{
while (running)
{
if (!connection.isOpen())
{
if (connected == true)
{
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Lost " + connectionType + " connection to "
+ intfc.getName() + "(" + intfc.getIp() + ") on port " + port);
}
connected = false;
setStatus("Disconnected");
monitoringThread.interrupt();
}
else
{
connected = true;
}
TimeUnit.SECONDS.sleep(connectionMonitorIntervalInSeconds);
}
}
catch (InterruptedException ex)
{
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Monitoring thread for " + connectionType
+ " connection to " + intfc.getName() + " interrupted");
}
}
};
monitoringThread.setName(intfc.getName() + " " + connectionType + " Monitoring Thread");
monitoringThread.start();
}

concurrent modification on arraylist

There are a lot of concurrent mod exception questions, but I'm unable to find an answer that has helped me resolve my issue. If you find an answer that does, please supply a link instead of just down voting.
So I originally got a concurrent mod error when attempting to search through an arraylist and remove elements. For a while, I had it resolved by creating a second arraylist, adding the discovered elements to it, then using removeAll() outside the for loop. This seemed to work, but as I used the for loop to import data from multiple files I started getting concurrent modification exceptions again, but intermittently for some reason. Any help would be greatly appreciated.
Here's the specific method having the problem (as well as the other methods it calls...):
public static void removeData(ServiceRequest r) {
readData();
ArrayList<ServiceRequest> targets = new ArrayList<ServiceRequest>();
for (ServiceRequest s : serviceQueue) {
//ConcurrentModification Exception triggered on previous line
if (
s.getClient().getSms() == r.getClient().getSms() &&
s.getTech().getName().equals(r.getTech().getName()) &&
s.getDate().equals(r.getDate())) {
JOptionPane.showMessageDialog(null, s.getClient().getSms() + "'s Service Request with " + s.getTech().getName() + " on " + s.getDate().toString() + " has been removed!");
targets.add(s);
System.out.print("targetted"); }
}
if (targets.isEmpty()) { System.out.print("*"); }
else {
System.out.print("removed");
serviceQueue.removeAll(targets);
writeData(); }
}
public static void addData(ServiceRequest r) {
readData();
removeData(r);
if (r.getClient().getStatus().equals("MEMBER") || r.getClient().getStatus().equals("ALISTER")) {
serviceQueue.add(r); }
else if (r.getClient().getStatus().equals("BANNED") || r.getClient().getStatus().equals("UNKNOWN")) {
JOptionPane.showMessageDialog(null, "New Request failed: " + r.getClient().getSms() + " is " + r.getClient().getStatus() + "!", "ERROR: " + r.getClient().getSms(), JOptionPane.WARNING_MESSAGE);
}
else {
int response = JOptionPane.showConfirmDialog(null, r.getClient().getSms() + " is " + r.getClient().getStatus() + "...", "Manually Overide?", JOptionPane.OK_CANCEL_OPTION);
if (response == JOptionPane.OK_OPTION) {
serviceQueue.add(r); }
}
writeData(); }
public static void readData() {
try {
Boolean complete = false;
FileReader reader = new FileReader(f);
ObjectInputStream in = xstream.createObjectInputStream(reader);
serviceQueue.clear();
while(complete != true) {
ServiceRequest test = (ServiceRequest)in.readObject();
if(test != null && test.getDate().isAfter(LocalDate.now().minusDays(180))) {
serviceQueue.add(test); }
else { complete = true; }
}
in.close(); }
catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }
}
public static void writeData() {
if(serviceQueue.isEmpty()) { serviceQueue.add(new ServiceRequest()); }
try {
FileWriter writer = new FileWriter(f);
ObjectOutputStream out = xstream.createObjectOutputStream(writer);
for(ServiceRequest r : serviceQueue) { out.writeObject(r); }
out.writeObject(null);
out.close(); }
catch (IOException e) { e.printStackTrace(); }
}
EDIT
The changes cause the concurrent mod to trigger every time rather than intermittently, which I guess means the removal code is better but the error now triggers at it.remove();
public static void removeData(ServiceRequest r) {
readData();
for(Iterator<ServiceRequest> it = serviceQueue.iterator(); it.hasNext();) {
ServiceRequest s = it.next();
if (
s.getClient().getSms() == r.getClient().getSms() &&
s.getTech().getName().equals(r.getTech().getName()) &&
s.getDate().equals(r.getDate())) {
JOptionPane.showMessageDialog(null, s.getClient().getSms() + "'s Service Request with " + s.getTech().getName() + " on " + s.getDate().toString() + " has been removed!");
it.remove(); //Triggers here (line 195)
System.out.print("targetted"); }
}
writeData(); }
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificatio
nException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at data.ServiceRequest.removeData(ServiceRequest.java:195)
at data.ServiceRequest.addData(ServiceRequest.java:209) <...>
EDIT
After some more searching, I've switch the for loop to:
Iterator<ServiceRequest> it = serviceQueue.iterator();
while(it.hasNext()) {
and it's back to intermittently triggering. By that I mean the first time I attempt to import data (the removeData method is being triggered from the addData method) it triggers the concurrent mod exception, but the next try it pushes past the failure and moves on to another file. I know there's a lot of these concurrent mod questions, but I'm not finding anything that helps in my situation so links to other answers are more than welcome...
This is not how to do it, to remove elements while going through a List you use an iterator. Like that :
List<ServiceRequest> targets = new ArrayList<ServiceRequest>();
for(Iterator<ServiceRequest> it = targets.iterator(); it.hasNext();) {
ServiceRequest currentServReq = it.next();
if(someCondition) {
it.remove();
}
}
And you will not get ConcurrentModificationException this way if you only have one thread.
If there is multiple threads involved in your code, you may still get ConcurrentModificationException. One way to solve this, is to use Collections.synchronizedCollection(...) on your collection (serviceQueue) and as a result you will get a synchronized collection that will not produce ConcurrentModificationException. But, you code may become very slow.

Where to use Thread interupt

I have some old code I am working with, and I'm not too experienced with Threads (mostly work on the front end). Anyway, this Thread.sleep is causing the thread to hang and I'm unsure what to do about it. I thought about using a counter and throwing a Thread.currentThread.interupt, but unsure of where to put it or which thread it will interupt. Here is an example of the dump. As you can see the thread count is getting pretty high at 1708.
Any advice?
"Thread-1708" prio=6 tid=0x2ceec400 nid=0x2018 waiting on condition
[0x36cdf000] java.lang.Thread.State: TIMED_WAITING (sleeping) at
java.lang.Thread.sleep(Native Method) Locked ownable synchronizers:
- None "Thread-1707" prio=6 tid=0x2d16b800 nid=0x215c waiting on condition [0x36c8f000] java.lang.Thread.State: TIMED_WAITING
(sleeping) at java.lang.Thread.sleep(Native Method) Locked ownable
synchronizers:
- None
#Override
public void run()
{
Connection con = null;
int i = 0;
while (is_running)
{
try
{
con = ConnectionManager.getConnection();
while (!stack.isEmpty())
{
COUNT++;
String line = (String) stack.pop();
getPartMfr(line);
try
{
if (this.mfr != null && !this.mfr.equals(EMPTY_STR))
{
lookupPart(con, line);
}
}
catch (SQLException e)
{
e.printStackTrace();
}
if (COUNT % 1000 == 0)
{
Log log = LogFactory.getLog(this.getClass());
log.info("Processing Count: " + COUNT);
}
}
}
catch (NamingException e)
{
e.printStackTrace();
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
ConnectionManager.close(con);
}
catch (SQLException e)
{
e.printStackTrace();
}
}
try {
Thread.sleep(80);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.finished = true;
}
Here is where it calls the run method, as you can see it does set it to false, but I guess it is missing threads?
HarrisWorker w[] = new HarrisWorker[WORKER_POOL_SIZE];
try
{
for (int i = 0; i < w.length; i++)
{
w[i] = new HarrisWorker(pw);
w[i].start();
}
pw.println(headers());
File inputDir = new File(HARRIS_BASE);
String files[] = inputDir.list();
for (String file : files)
{
try
{
File f = new File(HARRIS_BASE + File.separator + file);
if (f.isDirectory())
continue;
final String workFile = workDir + File.separator + file;
f.renameTo(new File(workFile));
FileReader fr = new FileReader(workFile);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
boolean firstLine = true;
while (line != null)
{
if (firstLine)
{
firstLine = false;
line = br.readLine();
continue;
}
if (line.startsWith(","))
{
line = br.readLine();
continue;
}
// if(line.indexOf("103327-1") == -1)
// {
// line = br.readLine();
// continue;
// }
HarrisWorker.stack.push(line);
line = br.readLine();
}
br.close();
fr.close();
for (int i = 0; i < w.length; i++)
{
w[i].is_running = false;
while (!w[i].finished)
{
Thread.sleep(80);
}
}
move2Processed(file, workFile);
long etime = System.currentTimeMillis();
System.out.println("UNIQUE PARTS TOTAL FOUND: " + HarrisWorker.getFoundCount() + " of " + HarrisWorker.getUniqueCount() + ", "
+ (HarrisWorker.getFoundCount() / HarrisWorker.getUniqueCount()));
System.out.println("Time: " + (etime - time));
}
catch (Exception e)
{
e.printStackTrace();
File f = new File(workDir + File.separator + file);
if (f.exists())
{
f.renameTo(new File(HARRIS_BASE + File.separator + ERROR + File.separator + file));
}
}
}
}
As a direct answer to the question in your title - nowhere. There is nowhere in this code that needs a Thread.interrupt().
The fact that the thread name is Thread-1708 does not necessarily mean there are 1708 threads. One can choose arbitrary names for threads. I usually include the name of the executor or service in the thread name. Maybe 1600 are now long stopped and there are only around a hundred alive. Maybe this particular class starts naming at 1700 to distinguish from other uses.
1708 threads may not be a problem. If you have a multi-threaded server that is serving 2000 connections in parallel, then it certainly expectable that there are 2000 threads doing that, along with a bunch of other threads.
You have to understand why the sleep is there and what purpose it serves. It's not there to just hog memory for nothing.
Translating the code to "plaintext" (btw it can be greatly simplified by using try-with-resources to acquire and close the connection):
Acquire a connection
Use the connection to send (I guess) whatever is in the stack
When failed or finished - wait 80ms (THIS is your sleep)
If run flag is still set - repeat from step 1
Finish the thread.
Now reading through this, it's obvious that it's not the sleep that's the problem. It's that the run flag is not set to false. And your thread just continues looping, even if it can't get the connection at all - it will simply spend most of its time waiting for the retry. In fact - even if you completely strip the sleep out (instead of interrupting it mid-way), all you will achieve is that the Threads will start using up more resources. Given that you have both a logger and you print to stdout via printStackTrace, I would say that you have 2 problems:
Something is spawning threads and not stopping them afterwards (not setting their run flag to false when done)
You are likely getting exceptions when getting the Connection, but you never see them in the log.
It might be that the Thread is supposed to set it's own run flag (say when the stack is drained), but you would have to decide that yourself - that depends on a lot of specifics.
Not an answer but some things you should know if you are writing code for a live, production systemn:
:-( Variable and method both have the same name, run. A better name for the variable might be keep_running Or, change the sense of it so that you can write while (! time_to_shut_down) { ... }
:-( Thread.sleep(80) What is this for? It looks like a big red flag to me. You can never fix a concurrency bug by adding a sleep() call to your code. All you can do is make the bug less likely to happen in testing. That means, when the bug finally does bite, it will bite you in the production system.
:-( Your run() method is way too complicated (the keyword try appears four times). Break it up, please.
:-( Ignoring five different exceptions catch (MumbleFoobarException e) { e.printStackTrace(); } Most of those exceptions (but maybe not the InterruptedException) mean that something is wrong. Your program should do something more than just write a message to the standard output.
:-( Writing error messages to standard output. You should be calling log.error(...) so that your application can be configured to send the messages to someplace where somebody might actually see them.

ZeroMQ - jzmq .recvZeroCopy() fails to get any message while .recv() works

So I am writing my own piece of stuff using jzmq GIT master branch and ZeroMQ 3.2.3.
After installation I tried to test the following simple PUB/SUB program, where a publisher and a subscriber talk in a single process. Since the test is under Windows, I used TCP.
public class ZMQReadynessTest {
private ZMQ.Context context;
#Before
public void setUp() {
context = ZMQ.context(1);
}
#Test
public void testSimpleMessage() {
String topic = "tcp://127.0.0.1:31216";
final AtomicInteger counter = new AtomicInteger();
// _____________________________________ create a simple subscriber
final ZMQ.Socket subscribeSocket = context.socket(ZMQ.SUB);
subscribeSocket.connect(topic);
subscribeSocket.subscribe("TestTopic".getBytes());
Thread subThread = new Thread() {
#Override
public void run() {
while (true) {
String value = null;
// This would result in trouble /\/\/\/\/\/\/\/\/\
{
ByteBuffer buffer = ByteBuffer.allocateDirect(100);
if (subscribeSocket.recvZeroCopy( buffer,
buffer.remaining(),
ZMQ.DONTWAIT
) > 0 ) {
buffer.flip();
value = buffer.asCharBuffer().toString();
System.out.println(buffer.asCharBuffer().toString());
}
}
// This works perfectly + + + + + + + + + + + + +
/*
{
byte[] bytes = subscribeSocket.recv(ZMQ.DONTWAIT);
if (bytes == null || bytes.length == 0) {
continue;
}
value = new String(bytes);
}
*/
if (value != null && value.length() > 0) {
counter.incrementAndGet();
System.out.println(value);
break;
}
}
}
};
subThread.start();
// _____________________________ create a simple publisher
ZMQ.Socket publishSocket = context.socket(ZMQ.PUB);
publishSocket.bind("tcp://*:31216");
try {
Thread.sleep(3000); // + wait 3 sec to make sure its ready
} catch (InterruptedException e) {
e.printStackTrace();
fail();
}
// publish a sample message
try {
publishSocket.send("TestTopic".getBytes(), ZMQ.SNDMORE);
publishSocket.send("This is test string".getBytes(), 0);
subThread.join(100);
} catch (InterruptedException e) {
e.printStackTrace();
fail();
}
assertTrue(counter.get() > 0);
System.out.println(counter.get());
}
}
Now as you can see, in the subscriber if I use a simple .recv(ZMQ.DONTWAIT) method, it works perfectly. However, if I am using the direct byte buffer I got nothing returned - and I got the following exception, seems like on program exit:
Exception in thread "Thread-0" org.zeromq.ZMQException: Resource temporarily unavailable(0xb)
at org.zeromq.ZMQ$Socket.recvZeroCopy(Native Method)
at ZMQReadynessTest$1.run(ZMQReadynessTest.java:48)
I also tried to use a simple ByteBuffer (not a direct buffer), which doesn't throw the exception above; but also return me nothing.
Does anybody know how to resolve the above?
I don't want to create byte[] objects all around, as I am doing some high performance system. If this cannot be resolved, I might simply use Unsafe instead. But I really want to work in the "supposed way".
Thanks in advance.
Alex

Categories

Resources