Locking a method until another is done - java

I have an external API I have to call that requires a validation token. The app calling the API will be threaded. Also, only 5 concurrent connections are allowed. I'm going to use a fixed thread pool for the connections, but I'm having an issue with figuring out how to handle an expired/invalid token. What I want to do is, when one thread encounters an expired token, prevent the other threads from acquiring the token until it has been refreshed. I'm thinking of using ReentrantLock to do this, but I'm not sure if my implementation is correct.
public static void main(String[] args){
for(int i = 0; i < 100; i++){
new Thread(new LockTest()).start();
}
}
public void testLock(String message) throws InterruptedException{
try{
getToken(message);
/*
* Use token here
*/
Thread.sleep(1000);
Random r = new Random();
int num = r.nextInt((25-0) + 1);
if(num == 1){ //testing only - exception thrown randomly.
throw new Exception("Token Expired!");
}
System.out.println("Message: " + message);
}catch(Exception e){
System.err.println(e.getMessage());
awaitTokenRefresh = true;
refreshToken();
}
}
private void refreshToken() throws InterruptedException {
lock.lock();
try{
System.out.println("Refreshing token...");
Thread.sleep(2000l);
System.out.println("Refreshed!");
awaitTokenRefresh = false;
awaitRefresh.signalAll();
}
finally{
lock.unlock();
}
}
//test use case for salesforce token
private void getToken(String message) throws InterruptedException {
lock.lock();
try{
while(awaitTokenRefresh){
System.out.println(message + " waiting for token refresh...");
awaitRefresh.await();
}
}
finally{
lock.unlock();
}
}
public void run(){
try {
System.out.println("Starting thread...");
testLock(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Just for testing, I've put in some sleeps to mimic work being done. The main thing I don't know about is, when thread A unlocks inside of getToken() thread B enters, but we don't know if the token is invalid yet. So B could actually be getting a bad token that A has to find. Is there a good way to handle this? Or is the idea of using locks completely wrong?

The first thing I notice is that your code is not properly synchronized. The exception handler in testLock() modifies shared variable awaitTokenRefresh at a point where that write is not ordered relative to other threads reading its value in getToken().
The main thing I don't know about is, when thread A unlocks inside of getToken() thread B enters, but we don't know if the token is invalid yet. So B could actually be getting a bad token that A has to find. Is there a good way to handle this? Or is the idea of using locks completely wrong?
I guess what you really want to avoid is unnecessary token refreshes when the current token becomes invalid. Exactly one thread should refresh it; the others should simply wait for the refresh and then continue about their business. The problem with your approach is that the threads have no good way to determine whether they are the first to detect the expiration, and so should take responsibility for refreshing. And indeed that makes sense, because the concept of which thread does anything first is not always well defined in a multithreaded application.
Whether you use locks vs. synchronization is an implementation detail of relatively minor consequence. The key is that you must have some shared state that tells threads whether the token they propose to refresh is in fact still current at all. I might implement it something like this:
public class MyClass {
private Object token = null;
private final Object tokenMonitor = new Object();
// ...
private Object getToken() {
synchronized (tokenMonitor) {
if (token == null) {
return refreshToken(null);
} else {
return token;
}
}
}
private Object refreshToken(Object oldToken) {
synchronized (tokenMonitor) {
if (token == oldToken) { // test reference equality
token = methodToPerformARefreshAndGenerateANewToken();
}
return token;
}
}
// ...
}
The idea there is when it tries to refresh the token, each thread specifies which token it is trying to refresh. A refresh is performed only if that is in fact the current token, and either way, the current token is returned.
You could use a ReentrantLock in place of my tokenMonitor, with locking and unlocking instead of synchronized blocks, but I much prefer plain synchronization when the scope is well contained, as in this case. Among other things, it's safer -- when you leave a synchronized block, you leave it; there is no possibility of failing to release the relevant monitor. The same cannot be said for lock objects.

This actually looks a problem that can be solved with versioning:
public class LockTest {
private int currentVersion = -1;
private Object token = null;
private synchronized int refreshToken(int requestorVersion) {
if (requestorVersion == currentVersion) {
try {
//do the actual refresh
Thread.sleep(1000);
token = new Object();
currentVersion++;
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
return currentVersion;
}
public VersionedToken takeToken() {
if (currentVersion == -1) {
refreshToken(-1);
}
return new VersionedToken(currentVersion);
}
public class VersionedToken {
private int version;
public VersionedToken(int version) {
this.version = version;
}
private void refresh() {
version = refreshToken(version);
}
private Object getToken() {
return token;
}
}
public static void main(String[] args) {
LockTest t = new LockTest();
for (int i = 0; i < 5; i++) {
new Thread(() -> {
VersionedToken vtoken = t.takeToken();
Object token = vtoken.getToken();
try {
//do something with the token
}catch (Exception ex) {
//if token went bad - just refresh it and continue to work with it afterwords
vtoken.refresh();
token = vtoken.getToken();
}
}).start();
}
}
}

Related

Can Handler return a Future object?

Can I get a future object from a handler?
Handler handler = new Handler(getMainLooper());
Future<String> future = handler.post(new Callable<String>() {
public String call() throw Exception {
// run in the main thread
return askForPassword();
}
}); // can I do something like this?
String password = future.get(); // wait until finish
// do network things...
I have a network thread and I need to ask the user for password, since I need to show an input dialog I have to do this on Main thread, but handler can not return values.
I can do the same thing by
Handler handler = new Handler(getMainLooper());
String password = null;
handler.post(() -> {
// run in the main thread
password = askForPassword();
});
while (password == null) { /*wait until finish*/ }
// do network things...
But this looks stupid and inconvenient
Handler is fundamentally asynchronous and thus whatever you put there is not guaranteed to run immediately (moreover, you can postDelayed or postAtTime). Then it is clear, that you can not return any value from the Handler directly to the code that posted it. So you have to work this around.
Another obstacle is that in Java your closure can capture only final variables and you have to work this around as well.
New API (CompletableFuture)
Unfortunately original Future Java API is not suitable for composition. If you target new devices only and thus can use newer CompletableFuture, you may do something like this:
CompletableFuture<String> askForPasswordNewApi() {
// your UI code that creates Future
}
void doNetworkThingNewApi() {
// some network stuff
final CompletableFuture<String> passwordFutureWrapper = new CompletableFuture<String>();
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// run in the main thread
CompletableFuture<String> future = askForPasswordNewApi();
// bind the real future to the outer one
future.handle((r, ex) -> {
if (ex != null)
passwordFutureWrapper.completeExceptionally(ex);
else
passwordFutureWrapper.complete(r);
return 0;
});
}
});
// wait until finish
// don't forget to handle InterruptedException here
String password = passwordFutureWrapper.get();
// do more network things...
}
The idea is rather simple: create outer final variable passwordFutureWrapper that can be captured by the Handler and bind this wrapper to the real future
Side note: if your askForPassword already returns Future but you can't use the new API, you probably have re-implemented something similar to CompletableFuture anyway, so you just need to modify this code a bit to allow binding of one future to another.
Old API
If you can't use CompletableFuture in your code yet, but still somehow has a method with a Future-based signature:
Future<String> askForPasswordOldApi()
you may do it more explicitly:
void doNetworkThingOldApi() {
// some network stuff
final CountDownLatch syncLock = new CountDownLatch(1);
final Future<String>[] futureWrapper = new Future<String>[1];
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// run in the main thread
final CompletableFuture<String> future = askForPasswordOldApi();
futureWrapper[0] = future;
syncLock.countDown();
}
});
String password;
try {
// 1 minute should be quite enough for synchronization between threads
if (!syncLock.await(1, TimeUnit.MINUTES)) {
// log error, show some user feedback and then stop further processing
return;
}
password = futureWrapper[0].get(); // wait until finish
} catch (InterruptedException ex) {
// log error, show some user feedback and then stop further processing
return;
} catch (ExecutionException ex) {
// log error, show some user feedback and then stop further processing
return;
}
// do more network things...
}
The idea here is following:
Use single-element array as a simple container to work around final-closure limitations
Use CountDownLatch to ensure synchronization between the network and the UI threads i.e. that futureWrapper[0] is not null by the time we start waiting on the result with get.
Update (design for library API)
If you are designing API and want to have a single entry for login with different additional scenarios handled by a callback, I'd do using custom implementation of something similar to CompletableFuture:
public interface ResultHandler<T> {
void resolve(T result);
void cancel();
}
class ResultHandlerImpl<T> implements ResultHandler<T> {
enum State {
Empty,
Resolved,
Cancelled
}
private final Object _lock = new Object();
private State _state = State.Empty;
private T _result;
#Override
public void resolve(T result) {
synchronized (_lock) {
if (_state != State.Empty) // don't override current state
return;
_result = result;
_state = State.Resolved;
_lock.notifyAll();
}
}
#Override
public void cancel() {
synchronized (_lock) {
if (_state != State.Empty) // don't override current state
return;
_state = State.Cancelled;
_lock.notifyAll();
}
}
public boolean isCancelled() {
synchronized (_lock) {
return _state == State.Cancelled;
}
}
public boolean isDone() {
synchronized (_lock) {
return _state == State.Resolved;
}
}
public T get() throws InterruptedException, CancellationException {
while (_state == State.Empty) {
synchronized (_lock) {
_lock.wait();
}
}
if (_state == State.Resolved)
return _result;
else
throw new CancellationException();
}
}
I would probably make interface public but implementation ResultHandlerImpl package-private so it would be harder for the users to mess up with implementation details. Then in callback methods I'd pass my callback ResultHandler as a parameter (actually it obviously would be a ResultHandlerImpl):
public interface LoginCallback {
void askForPassword(ResultHandler<String> resultHandler);
}
And my login method would look something like this (assuming you have private methods tryRestoreSession that doesn't need password and loginWithPassword that requires):
public boolean login(final LoginCallback loginCallback) {
if (tryRestoreSession()) {
return true;
} else {
final ResultHandlerImpl<String> passwordHandler = new ResultHandlerImpl<>();
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// run in the main thread
loginCallback.askForPassword(passwordHandler);
}
});
String password;
try {
password = passwordHandler.get();
} catch (CancellationException e) {
return false;
} catch (InterruptedException e) {
return false;
}
return loginWithPassword(password);
}
}
What I think is important here:
I think that passing a callback to LoginCallback makes it easier to write an asynchronous UI-based implementation using standard Java.
ResultHandlerImpl has cancel method. So if the user, for example, forgot the password there is a way to cancel whole login process and not get stuck with a background thread waiting for a password forever
ResultHandlerImpl uses explicit synchronization and wait/notifyAll to establish happens-before relationship between actions on different threads to avoid.
ResultHandlerImpl uses wait/notifyAll so the background thread doesn't consume CPU (and battery) while waiting for the UI.
UPDATED using "wait and notify" instead of looping
UPDATED 2 synchronized methods
Finally I end up with object wrapper(thansk to #SergGr ) and handler
class ObjectWrapper<T> {
T object;
boolean ready;
synchronized void set(T object) {
this.object = object;
this.ready = true;
notifyAll();
}
T get() {
while (!ready) {
synchronized(this) {
try {
wait();
} catch (InterruptedException e) {
return null;
}
}
}
return object;
}
}
In my network thread
Handler handler = new Handler(getMainLooper());
ObjectWarpper<String> wrapper = new ObjectWarpper<>();
handler.post(() -> wrapper.set(askForPassword()));
String password = wrapper.get();

Java concurrency exercise. Asynchronous download

I'm doing an exercise about Java concurrency using wait, notify to study for an exam.
The exam will be written, so the code does have to be perfect since we can't try to compile and check errors.
This is the text of the exercise:
General idea:
when the downloader is instanced the queue and the hashmap are created and passed to all the threads. (shared data)
the download method add the url to the queue and call notifyAll to wake up the Downloader Threads.
the getData method waits until there are data in the hashmap for the provided url. When data are available it returns to the caller.
the downloader thread runs an infinity loop. It waits until an url is present in the queue. When it receives an url it downloads it and puts the bytes in the hashmap calling notifyAll to wake up a possible user waiting in getData method.
This is the code that I produced:
public class Downloader{
private Queue downloadQueue;
private HashMap urlData;
private final static THREADS_NUMBER;
public Downloader(){
this.downloadQueue = new Queue();
this.urlData = new HashMap();
for(int i = 0; i < THREADS_NUMBER; i++){
new DownTh(this.downloadQueue, this.urlData).start();
}
}
void syncronized download(String URL){
downloadQueue.add(url);
notifyAll();
return;
}
byte[] syncronized getData(String URL){
while(urlData.get(URL) == null ){
wait()
}
return urlData.get(URL);
}
}
public class DownTh extend Thread{
private Queue downloadQueue;
private HashMap urlData;
public DownTh(Queue downloadQueue, HashMap urlData){
this.downloadQueue = downloadQueue
this.urlData = urlData;
}
public void run(){
while(true){
syncronized{
while(queue.isEmpty()){
wait()
}
String url = queue.remove();
urlData.add(url, Util.download(url))
notifyAll()
}
}
}
}
Can you help me and tell me if the logic is right?
Let's assume for a second that all those great classes in Java that handle synchronization do not exist, because this is a synthetic task, and all you got to handle is sychronized, wait and notify.
The first question to answer in simple words is: "Who is going to wait on what?"
The download thread is going to wait for an URL to download.
The caller is going to wait for the result of that download thread.
What does this mean in detail? We need at least one synchronization element between the caller and the download thread (your urlData), also there should be one data object handling the download data itself for convenience, and to check whether or not the download has yet been completed.
So the detailed steps that will happen are:
Caller requests new download.create: DownloadResultwrite: urlData(url -> DownloadResult)wake up 1 thread on urlData.
Thread X must find data to download and process it or/then fall asleep again.read: urlData (find first unprocessed DownloadResult, otherwise wait on urlData)write: DownloadResult (acquire it)write: DownloadResult (download result)notify: anyone waiting on DownloadResultrepeat
Caller must be able to asynchronously check/wait for download result.read: urlDataread: DownloadResult (wait on DownloadResult if required)
As there are reads and writes from different threads on those objects, synchronization is required when accessing the objects urlData or DownloadResult.
Also there will be a wait/notify association:
caller -> urlData -> DownTh
DownTh -> DownloadResult -> caller
After careful analysis the following code would fulfill the requirements:
public class DownloadResult {
protected final URL url; // this is for convenience
protected boolean inProgress;
protected byte[] result;
public DownloadResult(final URL url) {
this.url = url;
this.inProgress = false;
}
/* Try to lock this against tother threads if not already acquired. */
public synchronized boolean acquire() {
if (this.inProgress == false) {
this.inProgress = true;
return true;
} else {
return false;
}
}
public void download() {
final byte[] downloadedBytes = Util.download(this.url); // note how this is done outside the synchronized block to avoid unnecessarily long blockings
synchronized (this) {
this.result = downloadedBytes;
this.notifyAll(); // wake-up ALL callers
}
}
public synchronized byte[] getResult() throws InterruptedException {
while (this.result == null) {
this.wait();
}
return this.result;
}
}
protected class DownTh extends Thread {
protected final Map<URL, DownloadResult> urlData;
public DownTh(final Map<URL, DownloadResult> urlData) {
this.urlData = urlData;
this.setDaemon(true); // this allows the JVM to shut down despite DownTh threads still running
}
protected DownloadResult getTask() {
for (final DownloadResult downloadResult : urlData.values()) {
if (downloadResult.acquire()) {
return downloadResult;
}
}
return null;
}
#Override
public void run() {
DownloadResult downloadResult;
try {
while (true) {
synchronized (urlData) {
while ((downloadResult = this.getTask()) == null) {
urlData.wait();
}
}
downloadResult.download();
}
} catch (InterruptedException ex) {
// can be ignored
} catch (Error e) {
// log here
}
}
}
public class Downloader {
protected final Map<URL, DownloadResult> urlData = new HashMap<>();
// insert constructor that creates the threads here
public DownloadResult download(final URL url) {
final DownloadResult result = new DownloadResult(url);
synchronized (urlData) {
urlData.putIfAbsent(url, result);
urlData.notify(); // only one thread needs to wake up
}
return result;
}
public byte[] getData(final URL url) throws InterruptedException {
DownloadResult result;
synchronized (urlData) {
result = urlData.get(url);
}
if (result != null) {
return result.getResult();
} else {
throw new IllegalStateException("URL " + url + " not requested.");
}
}
}
In real Java things would be done differently, by using Concurrent classes and/or Atomic... classes, so this is just for educational purposes. For further reading see "Callable Future".

Should Thread.sleep be used when reading from a FIFO?

Due to the fact that in almost every question regarding the use of Thread.sleep it is mostly indicated to use it only in certain situations, I come to ask you if it is correct to use it in my case or if there is a better way to do it.
The operating system is Linux(Debian), in which a bash script is running that is detecting when a device (more specifically, a storage device) is inserted/removed, and then writes into a FIFO a string under the type "ADD {path-to-dev}" or "REM {path-to-dev}".
I created a small app in java which makes use of two threads. The first thread will call upon a read method that parses the String to the standard output, after which it will wait(). The second thread will check if the FIFO is empty or not and then, when it sees that a String has been inserted then it will call notify() so the other thread will print the String in there and so on. Inside the loop where it checks if the FIFO has data or not, I call Thread.sleep(1000), and I am unsure whether this is a good approach or not. I will present the code which handles all the action.
First, the class which has the methods of reading:
public class Detect {
private File file;
private BufferedReader read;
private volatile boolean readable;
private static String readFromFile;
public Detect() throws FileNotFoundException {
file = new File("/hardware_stuff/hardware_events");
read = new BufferedReader(new FileReader(file));
readable = true;
}
synchronized String readFromFifo() {
while (!readable) {
try {
wait();
} catch (InterruptedException ex) {
System.out.println("Interrupted during the wait for read.");
}
}
try {
while (read.ready()) {
readFromFile = read.readLine();
}
} catch (IOException ex) {
System.out.println("Error in reading from FIFO.");
}
readable = false;
notify();
return readFromFile;
}
synchronized void waitForFifo() {
while (readable) {
try {
wait();
} catch (InterruptedException ex) {
Logger.getLogger(Detect.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
while (!read.ready()) {
Thread.sleep(1000);
System.out.println("Sleeping due to lack of activity in FIFO in thread : " + Thread.currentThread().getName());
}
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Detect.class.getName()).log(Level.SEVERE, null, ex);
}
readable = true;
notify();
}}
Next, the thread which will read from it.
public class ReadThread extends Thread {
Detect detect;
private boolean shouldBeRunning;
public ReadThread(Detect detect) {
this.detect = detect;
shouldBeRunning = true;
}
#Override
public void run() {
while (shouldBeRunning) {
String added = detect.readFromFifo();
System.out.println(added);
}
}
public void stopRunning() {
shouldBeRunning = false;
}}
Finally, the thread which will check if the FIFO is empty or not.
public class NotifyThread extends Thread {
Detect detect;
private boolean shouldBeRunning;
public NotifyThread(Detect detect) {
this.detect = detect;
shouldBeRunning = true;
}
#Override
public void run() {
while (shouldBeRunning) {
detect.waitForFifo();
}
}
public void stopRunning() {
shouldBeRunning = false;
}}
In main I just create the threads and start them.
Detect detect = new Detect();
NotifyThread nThread = new NotifyThread(detect);
ReadThread rThread = new ReadThread(detect);
nThread.start();
System.out.println("Started the notifier thread in : " + Thread.currentThread().getName());
rThread.start();
System.out.println("Started the reading thread in : " + Thread.currentThread().getName());
Is there any alternative to calling sleep or another approach I can take to replace the sleep with something else? I have already read other questions related to this topic and I am still uncertain/have not understood whether this sort of case is indicated for sleep or not.
UPDATE: As #james large said, there was no need to poll for ready. I was not aware that if there is no line, the readLine() will 'sleep' and there was no need to poll it after all. I removed the notifier thread, and I simply kept the ReadThread which will call the Detect readFromFifo() method and it all works good. #dumptruckman, thanks for the suggestion. Although it doesn't apply to my case, I didn't know of the WatchService and it was a good read, good stuff to know. #Nyamiou The Galeanthrope, the timer would have been useful, but as I already said, I only keep one thread to execute the same method and it works as intended.#Krzysztof Cichocki, thanks for pointing out there are issues. I was aware of that, otherwise I wouldn't have asked this question.

Thread safe access to arraylist: two producer one consumer. Lock object is enough?

I have two thread that can produce value and add it in a arraylist,
and other thread can access to it to read a value.
My problem is that the producer can access to the list in the same time that the consumer use data.
This is my code :
public class CommandTree
{
Lock lock = new ReentrantLock();
ArrayList<Command> cmdToSend = null;
JSONObject sendCmdMap;
public CommandTree(JSONObject sendCmdMap)
{
this.cmdToSend = new ArrayList<Command>();
this.sendCmdMap = sendCmdMap;
}
private synchronized void addMacroCmd(String macro, int fmt, int tgt, int sid,int count,JSONArray sli,String paramName,JSONObject params,int function)
{
boolean check = false;
int i = 0;
lock.lock();
try
{
for(i=0; i<cmdToSend.size(); i++)
{
if(cmdToSend.get(i).getMacroName().equalsIgnoreCase(macro))
{
check = true;
break;
}
}
if(check == false)
{
cmdToSend.add(new Command(macro,fmt,tgt,sid,count,function,sli));
}
if(paramName != null)
{
if(check)
cmdToSend.get(i).setParameter(paramName,params);
else
cmdToSend.get(cmdToSend.size()-1).setParameter(paramName,params);
}
}
finally
{
lock.unlock();
}
}
private void addParameter(String macro,int fmt, int tgt, int sid,int count,JSONArray sli,String paramName,JSONObject params,int function)
{
lock.lock();
try
{
this.addMacroCmd(macro, fmt, tgt, sid, count,sli, paramName,params,function);
}
finally
{
lock.unlock();
}
}
public int getSize()
{
return cmdToSend.size();
}
public void reset()
{
lock.lock();
try
{
cmdToSend.clear();
}
finally
{
lock.unlock();
}
}
/*
public Command getNextCommandInLoop()
{
return cmdToSend.;
}
*/
public Command getNextCommand(int i)
{
Command result;
lock.lock();
try
{
result = cmdToSend.get(i);
}
finally
{
lock.unlock();
}
return result;
}
public synchronized boolean populateCommandTree(String i,String target) throws JSONException
{
JSONObject tgtCmd = (JSONObject) sendCmdMap.get(target);
JSONObject cmdObject;
Iterator<String> iter = tgtCmd.keys();
while (iter.hasNext())
{
String key = iter.next();
if(key.equalsIgnoreCase(i))
{
//it is a general commands
JSONObject macro = (JSONObject)tgtCmd.opt(key);
cmdObject = (JSONObject) macro.opt("cmd");
addMacroCmd(key,cmdObject.optInt("fmt"),cmdObject.optInt("tgt"),cmdObject.optInt("sid"),cmdObject.optInt("count"),cmdObject.optJSONArray("sli"),null,null,macro.optInt("function"));
return true;
}
else
{
//It is a parameter, we have to search its general command
cmdObject = (JSONObject)tgtCmd.opt(key);
if(cmdObject == null)
{
continue;
}
JSONObject parameter = cmdObject.optJSONObject("Parameter");
if( parameter == null)
{
//There isn't the requested command, we iterate on the next one
continue;
}
else
{
if(((JSONObject) parameter).optJSONObject(i) != null)
{
JSONObject cmdStructure = (JSONObject)cmdObject.opt("cmd");
//We have found the command, save it in commandSendCache
addMacroCmd(key,cmdStructure.optInt("fmt"),cmdStructure.optInt("tgt"),cmdStructure.optInt("sid"),cmdStructure.optInt("count"),cmdStructure.optJSONArray("sli"),i,parameter.optJSONObject(i),cmdObject.optInt("function"));
return true;//(JSONObject)tgtCmd.opt(key);
}
else
{
continue;
}
}
}
}
return false;
}}
I read some post on that case, but I don't understand very well. I thought to post my code in this way I can understand in better way.
Other problem is that one producer is a UI thread, and I worried if there is problem to stop the UI thread for some times.
I also thought to use ConcurrentLinkedQueue because some time I need to loop on the list, and I always extract the value from the first position, but with concurrentLInkedQueue I don't know how can implementate the loop and in what way I can implementate the addMacroCmd method..
In my case I think to use lock object and ArrayList.
Do you have some suggestion ? I want to learn in better way the concurrency, but it not very easy for me :(
EDIT : the following is the part of code that add and remove the command :
public synchronized void readSensorData(String[] sensor, String target)
{
cmdTree.reset();
for(int i=0;i<sensor.length;i++)
{
try
{
cmdTree.populateCommandTree(sensor[i],target);
}
catch (JSONException e)
{
}
}
writeExecutor.execute(this.writeCommandTree);
}
/**
*
* #param i
* #param target
* #return
* #throws JSONException when the command requested doesn't exists
*/
private ByteArrayOutputStream f = new ByteArrayOutputStream();
ExecutorService writeExecutor = Executors.newSingleThreadExecutor();
Semaphore mutex = new Semaphore(0);
volatile boolean diagnostic = false;
volatile int index = 0;
Runnable writeCommandTree = new Runnable()
{
#Override
public void run()
{
while(index < cmdTree.getSize())
{
writeCmd();
try
{
mutex.acquire();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
sendAnswerBroadcast("answer", answer);
answer = new JSONObject();
index = 0;
}
};
and the mutex is release when arrive a new response .
Addictional information :
The readSensorData() is called when button on the ux (UI Thread) is
pressed and in same case from other Thread B. WriteCommandTree is only
execute in the executor (Other Thread C).
I change the name of getnextcommand into getcommand
- getcommand(int i) is called in the callback of the response (sometime is in other thread (i'm forget to that function ...) and in writecmd inside writecommandtree
- getsize in the writecommandTree in the thread C
Don't get headaches just for synchronizing a list, simply use the Java standard library :
List<Command> commands = Collections.synchronizedList(new ArrayList<>());
By the way, a naive implementation of this would simply to wrap an unsafe list and add synchronized to all the methods.
You can use blockingQueue to achieve the same. Refer simple tutorial about blockingQueue :http://tutorials.jenkov.com/java-util-concurrent/blockingqueue.html
There are several problems with this code:
It is unlikely that you need both a ReentrantLock and synchronization.
The getSize method is not synchronized at all. If, e.g., reset is called from a thread other than the one from which getSize is called, the program is incorrect.
sendCmdMap is leaked in CommandTree's constructor. If the thread that creates the CommandTree is different from the thread that calls populateCommandTree, the program is incorrect.
Note, btw, that using a synchronized view of cmdToSend would not fix any of these problems.
What you need to do, here, is this:
Producers need to seize a lock, hand a command to the CommandTree and then delete all references to it.
Consumers need to seize the same lock and get a reference to a command, deleting it from the CommandTree.
For problems like this, there is no better reference than "Java Concurrency in Practice"

Queue Error in java

I had implemented a asynchronous thread by a singleton class in which a queue is present to which i add logging object.
But it is giving no such element exception at java.util.linkedlist.remove
public class LogDaoSingleton extends Thread {
private static LogDaoSingleton logDaoSingleton = new LogDaoSingleton();
private static Queue<ScoreLoggingObject> queue = new LinkedList<ScoreLoggingObject>();
private static Boolean firstTime = true;
private LogDAO logDAO;
private SkipLogDaoImpl skipLogDAO;
Connection conNull = null;
Connection connection = null;
private int counter = 0;
Connection con = null;
Connection skipCon = null;
public static LogDaoSingleton getInstance() {
return logDaoSingleton;
}
private static void createInstance() {
logDaoSingleton = new LogDaoSingleton();
}
private LogDaoSingleton() {
try {
con = HMDBUtil.getNonTxNullProdConnection();
conNull = HMDBUtil.getNonTxNullProdConnection();
skipCon = HMDBUtil.getNonTxNullProdConnection();
logDAO = new LogDAOImpl();
skipLogDAO = new SkipLogDaoImpl();
hmCandScoreLog = PropertyReader.getStringProperty(
CacheConstants.CLUSTER_REPORT,
CacheConstants.HM_CAND_SCORE_LOG);
hmCandScoreLogNull = PropertyReader.getStringProperty(
CacheConstants.CLUSTER_REPORT,
CacheConstants.HM_CAND_SCORE_LOG_NULL);
} catch (HMCISException e) {
e.printStackTrace();
}
}
public static void addtoQueue(ScoreLoggingObject scoringObject) {
queue.add(scoringObject);
if (firstTime) {
synchronized (firstTime) {
if (firstTime) {
createInstance();
logDaoSingleton.setDaemon(false);
logDaoSingleton.start();
firstTime = false;
}
}
}
}
public void run() {
try {
while (true) {
try {
if (null != queue && queue.size() > 0) {
logData(queue.poll());
} else {
try {
Thread.sleep(2 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
// Do nothing.
}
}
} catch (Throwable e) {
firstTime = true;
}
}
private void logData(ScoreLoggingObject scoreLoggingObject) {
}
}
}
Error is at logData(queue.poll());
There are at least three problems in this method:
public static void addtoQueue(ScoreLoggingObject scoringObject) {
queue.add(scoringObject);
if (firstTime) {
synchronized (firstTime) {
if (firstTime) {
createInstance();
logDaoSingleton.setDaemon(false);
logDaoSingleton.start();
firstTime = false;
}
}
}
}
Namely
That you are adding to a LinkedList without a lock. LinkedList is not a concurrency safe collection. Try ConcurrentSkipLinkedList as a better collection.
You are reading firstTime using double-checked locking... which can have side-effects that you might not believe... Go take a look at "Java Concurrency in Practice" specifically the Yuck-face listing on page 32. Try to predict what that program will output before reading the book. Then read the explanation. Unfortunately I am going to have to spoil the impact of that example for you now when I point out that the JVM is entitled to reorder operations in between synchronization points. So the result is that the operations within your synchronized block can be implemented in any order... for example they could happen in the following order (likely not, but a JVM implementation will still be valid if it did it in this order)
synchronized (firstTime) {
if (firstTime) {
firstTime = false;
createInstance();
logDaoSingleton.setDaemon(false);
logDaoSingleton.start();
}
}
What would happen if there is an exception thrown in your createInstance() method?
If it were me, I would fix that by making firstTime a volatile that would force the JVM to respect the ordering (though you would still need the double-check!)
firstTime is a Boolean initialized by auto-boxing, which for Boolean uses pooled instances, so your double-checked lock is actually synchronized (Boolean.TRUE) and not synchronized (firstTime). Additionally it is bad form to synchronize on a non-final field, as it almost never does what you want it to do. You probably want to just make the addToQueue method synchronized until you know you have a problem.
TL;DR you are trying to be 'clever' with locking... always a bad plan... especially before you know that you need to be clever. Write the simplest thing that could possibly work, then get on with the rest of the problems. Then see where the performance issues are... ONLY THEN should you worry about locking in this class.

Categories