I've a socket connect method in my class that's supposed to be called by only 1 thread at a time. Inside that synchronized method, I've a synchronized block based off an random object. I'm calling the synchronized connect method of my class from an Android service
Problem:
Sometimes the app goes into non responding state if the socketIO connection takes longer to establish connection when the socket URL is not reachable. I've no clue why this is happening.
class MyService extends Service {
public void onStartCommand() {
MyUtilClass.getInstance().init();
MyUtilClass.getInstance().startSomeOSBroadcastListeners();
MyUtilClass.getInstance().connectAsync();
}
}
class MyUtilClass {
private final Object tempObj = new Object();
private MyUtilClass mUtilClass;
public static MyUtilClass getInstance() {
if(mUtilClass == null)
mUtilClass = new MyUtilClass();
return mUtilClass;
}
public void init() {
startListeningSocketIoConnectEvent();
}
public MyUtilClass connectAsync() {
new Thread(new Runnable() {
connect();
}).start();
return this;
}
private synchronized MyUtilClass connect() {
synchronized(tempObj) {
mSocketIO.connect();
tempObject.wait();
}
return this;
}
private void startListeningSocketIoConnectEvent() {
mSocketIO.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
synchronized (mWaitLock) {
tempObj.notifyAll(); //releasing the lock
}
}
});
}
}
The tempObj is only being used for socketIO connection phase afterwards it's not used.
Why does it sometimes go into ANR state? Is this implementation correct?
Related
I have 2 threads, one calls get() method, another put() method.
I need to synchronize this methods in order to see result of get only after put. I do know how to do this other way, but I want to understand why am i getting .IllegalMonitorStateException with this code.
public class TransferObject {
private int value;
protected volatile boolean isValuePresent = false; //use this variable
public synchronized int get() {
synchronized (TransferObject.class) {
System.out.println("Got: " + value);
notify();
}
return value;
}
public void put(int value) {
synchronized (TransferObject.class) {
this.value = value;
System.out.println("Put: " + value);
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Here is example of 2 threads.
public class ConsumerTask implements Runnable {
private TransferObject transferObject;
protected volatile boolean stopped;
public ConsumerTask(TransferObject transferObject) {
this.transferObject = transferObject;
new Thread(this, "ConsumerTask").start();
}
public void run() {
while (!stopped) {
transferObject.get();
}
}
public void stop() {
stopped = true;
}
}
public class ProducerTask implements Runnable {
private TransferObject transferObject;
protected volatile boolean stopped;
static volatile AtomicInteger i = new AtomicInteger(0);
public ProducerTask(TransferObject transferObject) {
this.transferObject = transferObject;
new Thread(this, "ProducerTask").start();
}
public void run() {
while (!stopped) {
transferObject.put(i.incrementAndGet());
}
}
public void stop() {
stopped = true;
}
}
You have two threads and one object for locking TransferObject.class.
When your thread ConsumerTask gets the lock, object TransferObject.class don't have sleeping threads, and when you call notify() for this monitor you get IllegalMonitorStateException
From the description for method notify:
Wakes up a single thread that is waiting on this object's monitor.
You don't have waiting treads for monitor TransferObject.class
I have a singleton class which is also Runnable (and Observable). When I'm trying to start the thread from main, it does not create a new thread and gets stuck in the main loop.
public class A extends Observable implements Runnable
{
private static A instance = null;
private A() {
}
public static A getInstance() {
if(instance == null) {
instance = new A();
}
return instance;
}
#Override
public void run()
{
while (true) {
System.out.print("\nSleeping");
// sleep
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.print("\n[Error]");
}
}
}
}
and the main class:
Thread thread = new Thread(A.getInstance());
thread.run();
System.out.print("\nAfter...");
I cant see the "After" log, just the "Sleeping" in a loop. Why?
You're calling run(), instead of start().
I am new to Java and pulling some hair out on the application I'm working on. Here is what I am trying to do.
I have a client / server setup where I use QuickServer as the server. I got that up and running well. It sends and receives commands line by line with "\r"\n" so I have my client in a
public class CommandHandler extends Thread {
public void run() {
while (connected) {
//read and write
if (command.equals("USERNAME")) {
AsynchEventBusSingleton.$().postEvent(new TellParentToGiveUN())
}
...
}
}
My GUI freezes if I do not extend Thread so I presume the CommandHandler needs its own thread. The problem however is the AsyncEventBusSingleton.
public class AsyncEventBusSingleton {
private EventBus ebEventBus = null;
final static AsyncEventBusSingleton aebInstance = new AsyncEventBusSingleton();
public synchronized static AsyncEventBusSingleton $() {
return aebInstance;
}
private AsyncEventBusSingleton() {
ebEventBus = new AsyncEventBus(Executors.newCachedThreadPool());
}
public void registerSubscriber(Object subscriber) {
ebEventBus.register(subscriber);
}
public void unRegisterSubscriber(Object subscriber) {
ebEventBus.unregister(subscriber);
}
public synchronized void postEvent(Object e) {
ebEventBus.post(e);
}
}
When I call this class inside CommandHandler thread none of my other classes on the main thread receive the events. If I remove the "synchronized" keyword some of the events are received/repeated/an error is generated.
Everything seems to work fine if don't throw events from CommandHandler, but rather pass a reference of the class that instantiates the CommandHandler and have it call CommandHandler's methods:
public class ServerConnectionHandler {
private CommandHandler commandhandler;
public void ConnectToServer() {
commandhandler = new CommandHandler(this);
}
public void dispatchServerEvent() {
commandhandler.sendResponse("MyUN");
}
}
public class CommandHandler extends Thread {
private PrintWriter printWriter;
private ServerConnectionHandler serverconnectionhandler;
public sendResponse(String s) {
this.printWriter.println(s);
}
public void run() {
while (connected) {
//read and write
if (command.equals("USERNAME")) {
this.serverconnectionhandler.dispatchServerEvent();
}
...
}
}
What is the best practice for having the client listen for certain commands and dispatching events to respond?
EDIT:
Edited the question in response to #maress answer below.
I have a web service in java (async enabled), which when called performs a call to another service asynchronously. In my Controller I have this:
private boolean receivedEvent = false;
private final Object SYNC = new Object();
public Callable<String> doStuff()
{
callSomeAsyncFunction();
return new Callable<String> ()
{
#Override
public String call() throws Exception {
synchronized (SYNC)
{
while (receivedEvent == false)
{
SYNC.wait();
}
receivedEvent = false;
System.out.println("RETURN");
return "ok";
}
}
};
}
public void onMyEvent(MyEvent event)
{
synchronized (SYNC)
{
receivedEvent = true;
System.out.println("RECEIVED");
SYNC.notify();
}
}
EDIT: The notification never gets through. System.out.println("RETURN") is never called. The events are being received ('RECEIVED' is shown).
Now all I want to do is wait for the callSomeAsyncFunction() to finish executing. When done, it triggers an event on the handler public void onMyEvent(MyEvent event).
Any suggestions? I am not even sure if my approach makes sense at all.
Synchronize always on a final instance.
private MyEvent myEvent;
private final Object SYNC = new Object();
public Callable<String> doStuff()
{
callSomeAsyncFunction();
return new Callable<String> ()
{
#Override
public String call() throws Exception {
synchronized (SYNC)
{
while (myEvent == null)
{
SYNC.wait();
}
return "ok";
}
}
};
}
public void onMyEvent(MyEvent event)
{
synchronized (SYNC)
{
myEvent = event;
SYNC.notifyAll();
}
}
I wrote a simple class that uses AbstractQueuedSynchronizer. I wrote a class that represents a "Gate", that can be passed if open, or is blocking if closed. Here is the code:
public class GateBlocking {
final class Sync extends AbstractQueuedSynchronizer {
public Sync() {
setState(0);
}
#Override
protected int tryAcquireShared(int ignored) {
return getState() == 1 ? 1 : -1;
}
public void reset(int newState) {
setState(newState);
}
};
private Sync sync = new Sync();
public void open() {
sync.reset(1);
}
public void close() {
sync.reset(0);
}
public void pass() throws InterruptedException {
sync.acquireShared(1);
}
};
Unfortunately, if a thread blocks on pass method because gate is closed and some other thread opens the gate in meantime, the blocked one doesn't get interrupted - It blocks infinitely.
Here is a test that shows it:
public class GateBlockingTest {
#Test
public void parallelPassClosedAndOpenGate() throws Exception{
final GateBlocking g = new GateBlocking();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
g.open();
} catch (InterruptedException e) {
}
}
});
t.start();
g.pass();
}
}
Please help, what should I change to make the gate passing thread acquire the lock successfully.
It looks like setState() only changes the state, but doesn't notify blocked threads about the change.
Therefore you should use acquire/release methods instead:
#Override
protected boolean tryReleaseShared(int ignored) {
setState(1);
return true;
}
...
public void open() {
sync.releaseShared(1);
}
So, overall workflow of AbstractQueuedSynchronizer looks like follows:
Clients call public acquire/release methods
These methods arrange all synchronization functionality and delegate actual locking policy to protected try*() methods
You define your locking policy in protected try*() methods using getState()/setState()/compareAndSetState()