Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread Status Monitor. How do I debug this? What's causing it?

I'm developing on Android and I can't figure out why some of my threads are going into a "monitor" status. I've read it could be because of a "synchronized" issue but I'm not sure how an object wouldn't release their lock.

Can anyone help with how to debug this or do you see anything I'm doing wrong? Is it an issue of synchronized objects not being released or is my loading not timing out properly and locking all the threads?

enter image description here

Here's how I'm using synchronized.

private Bitmap getFromSyncCache(String url) {
    if (syncCache == null) return null;
    synchronized (syncCache) {
        if (syncCache.hasObject(url)) {
            return syncCache.get(url);
        } else {
            return null;
        }
    }
}

and here:

bitmapLoader.setOnCompleteListener(new BitmapLoader.OnCompleteListener() {
            @Override
            public void onComplete(Bitmap bitmap) {
                if (syncCache != null) {
                    synchronized (syncCache) {
                        syncCache.put(bitmapLoader.getLoadUrl(), bitmap);
                    }
                }
                if (asyncCache != null) addToAsyncCache(bitmapLoader.getLoadUrl(), bitmap);
                if (onCompleteListener != null) onCompleteListener.onComplete(bitmap);
            }
        });

and here's my cache

public class MemoryCache<T> implements Cache<T>{

private HashMap<String, SoftReference<T>> cache;

public MemoryCache() {
    cache = new HashMap<String, SoftReference<T>>();
}

@Override
public T get(String id) {
    if(!cache.containsKey(id)) return null;
    SoftReference<T> ref = cache.get(id);
    return ref.get();
}

@Override
public void put(String id, T object) {
    cache.put(id, new SoftReference<T>(object));
}

@Override
public void clearCache() {
    cache.clear();
}

@Override
public boolean hasObject(String id) {
    return cache.containsKey(id);
}

and this is how I'm loading the image from the web:

private void threadedLoad(String url) {
    cancel();
    bytesLoaded = 0;
    bytesTotal = 0;
    try {
        state = State.DOWNLOADING;
        conn = (HttpURLConnection) new URL(url).openConnection();
        bytesTotal = conn.getContentLength();

        // if we don't have a total can't track the progress
        if (bytesTotal > 0 && onProgressListener != null) {
            // unused               
        } else {
            conn.connect();
            inStream = conn.getInputStream();
            Bitmap bitmap = BitmapFactory.decodeStream(inStream);
            state = State.COMPLETE;
            if (state != State.CANCELED) {
                if (bitmap != null) {
                    msgSendComplete(bitmap);
                } else {
                    handleIOException(new IOException("Skia could not decode the bitmap and returned null. Url: " + loadUrl));
                }
            }
            try {
                inStream.close();
            } catch(Exception e) {

            }
        }
    } catch (IOException e) {
        handleIOException(e);
    }
}
like image 538
user123321 Avatar asked Aug 24 '12 19:08

user123321


1 Answers

A way to check if it's indeed a deadlock is to use Android Studio's debugger: view the threads, right click on the threads that are in the "MONITOR" state and then click "Suspend." The debugger will take you to the line in the code at which the thread is stuck.

enter image description here

When I was debugging my deadlock, both threads turned out to be waiting on the synchronized statements.

like image 66
Nebel22 Avatar answered Nov 19 '22 16:11

Nebel22