This can happen when the item in our ListView contains a picture, and the images are the same resource, and we use multithreading to load the images.
For example, the thread is a person, the first person to do loading pictures to the cache work, not ready when the second person to the same picture, the result cache has not this picture, so the second person also to load the image to the cache. And so on, while there may be n people loading the same picture, N depends on the number of visible item before the picture is loaded into the cache.
Therefore, the detailed synchronization is done to avoid the occurrence of this situation.
// First, a concurrenthashmap<string is required, boolean>,string represents the resource address slice address, and Boolean indicates whether the thread is loading. // The reason for using Concurrenthashmap is that it is not only synchronous but also more efficient than synchronized and reentrantlock. Private Concurrenthashmap<string, boolean> mconcurentmap; // a reentrantlock is then required to lock the key judgment statement within the thread. private reentrantlock mLock;
when a thread does not find a resource in the cache, it reads the resource, Concurrenthashmap records the resource address, and the Boolean is true, indicating that someone is doing the job, and the following people just wait for the work to finish.
//This is the thread that loads the picture when the picture is not found in the cache (Mbitmapcache.get (path) = = null) into this threadThread thread =NewThread () {@Override Public voidrun () {MLock.Lock();//Lock key judgment logic to avoid multiple threads in the same resource entering false logic (loading picture) if(Mconcurentmap.Get(path) = =false) { //Mconcurentmap adds a key-value pair that indicates that the resource has already been loadedMconcurentmap.put (Path,true); Mlock.unlock (); //Release the lock, the following thread enters the logic only true (wait for the first person to finish the work) if(Path! =NULL&& (!path.equals ("NULL")) && (!"". Equals (Path)) { //Loading PicturesITEM.BM = picturehelper.getcropimage (Path, -,true, -, Mactivity,7,true); //The picture is loaded and put into cache LRUCachembitmapcache.put (path, ITEM.BM); //set the key-value pair, false indicates that the resource for path has been loaded, or no one has loadedMconcurentmap.put (Path,false); } Else{ITEM.BM=NULL; //Invalid picture addressMconcurentmap.put (Path,false); } Message msg=NewMessage (); Msg.what=1; Handler.sendmessage (msg); } Else { //Release LockMlock.unlock (); //indicates someone is loading the picture, so wait for the load to finish with a dead loop while(true) { //False indicates that the load is complete, the cache already has a picture, should jump out of the loop if(Mconcurentmap.Get(path) = =false) { //LOGG.D ("Other Need break cycle"); Break; } } //logg.d ("Other go-out cycle"); if(Mbitmapcache.Get(path)! =NULL) {ITEM.BM= Mbitmapcache.Get(path); Message msg=NewMessage (); Msg.what=2; Handler.sendmessage (msg); } Else { Throw NewNullPointerException ("(mbitmapcache.get (path) = = null!"); } } } }; Executors.execute (thread);
Android ListView avoids multi-line loads load a single resource