Domanda

I have an application that uses a read write lock to prevent other methods from running when the so called "reconnect" method is called. Now, I want this "reconnect" method to only be called once at a time. For example, when Thread1 calls "reconnect" and while "reconnect" is executing, Thread2 calls it, it either immediately returns or waits until the call of Thread1 is finished and then returns. (Resulting in only one execution). As you can probably imagine I have an application that interacts with some API and when my session times out, it needs to reconnect but I don't want every thread creating a new connection since that would be completely unnecessary. I hope I provided enough information.

È stato utile?

Soluzione

It's preferable to maintain a lock object and synchronize on that, such as:

public class MyClass {

    private final Object lock = new Object();

    public void reconnect() {
        synchronized(lock) {
            ....
        }
    }

    ....
}

The reason is that when you use the synchronized keyword in a method signature, you're actually synchronizing on your MyClass instance. The problem is, any other code outside your class could also do that. For instance,

public class SomeOtherClass {
    public void go(final MyClass myClass) {
        synchronized(myClass) {
            wait(Integer.MAXIMUM_VALUE);
        }
    }
}

Now if some other thread wants to call myClass.reconnect(), they can't, because SomeOtherClass has taken the lock on the myClass instance.

Altri suggerimenti

Synchronized keyword prevents multiple threads from executing the function at the same time. Then you just need to check the state of the connection in your method.

public synchronized void reconnect() {
    if (!connection.isActive()) { // this method will depend on what type of connection you have
        // your code ...
    }
}

Essentially you just need reconnect() to be a no-op if the connection is already active.

I would probably not use a direct lock.

I would use just one thread to handle all the connect/reconnect actions and queue request objects to it. This is a little more complex, but:

  • Its more flexible because such a mechansim would allow both synchronous and asynchronous requests/replies.

  • It's easier to debug because the connect/reconnect only ever happens serially on one thread.

  • It's easy to add an extra connection to [whatever] if it's ever required or acceptable.

  • Timeouts, keep-alives and connection problems can be detected, and logged/rectified, even if there are no requests outstanding.

  • Plain hard-locks over operations that may potentially block for an extended time are just too worrying.

Maybe it's just me... :)

You need a flag and synchronization:

private boolean mReconnectNeeded;

public synchronized void reconnectIfNeeded() {
    if (mReconnectNeeded) {
        mReconnectNeeded = false;
        // reconnect; if it fails, set the flag again
    }
}

public synchronized void setReconnectNeeded() {
    mReconnectNeeded = true;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top