編輯:關於Android編程
在前面我們在解決線程同步問題的時候使用了synchronized關鍵字,今天我們來看看Java 5.0以後提供的線程鎖Lock.
Lock接口的實現類提供了比使用synchronized關鍵字更加靈活和廣泛的鎖定對象操作,而且是以面向對象的方式進行對象加鎖。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD48cD48cHJlIGNsYXNzPQ=="brush:java;"> @Override public void run() { while(true){ Lock lock = new ReentrantLock(); try { lock.lock(); Thread.sleep(new Random().nextInt(3000)); String data = readData(); System.out.print("讀取數據: " + data); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } }
讀寫鎖:分為讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥,這是由JVM控制的。
import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockTest { static ReadWriteLock rwl = new ReentrantReadWriteLock(); private static String data = null; public static void main(String[] args) { Runnable runnable1 = new MyRunnable1(); Runnable runnable2 = new MyRunnable2(); for(int i=0; i<3; i++){ new Thread(runnable1).start(); new Thread(runnable2).start(); } } static class MyRunnable1 implements Runnable{ @Override public void run() { writeData("" + new Random().nextInt(100)); } } static class MyRunnable2 implements Runnable{ @Override public void run() { readData(); } } private static void writeData(String var){ rwl.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + " 准備寫"); Thread.sleep(new Random().nextInt(3000)); data = var; System.out.println(Thread.currentThread().getName() + " 寫完畢"); } catch (InterruptedException e) { e.printStackTrace(); }finally{ rwl.writeLock().unlock(); } } private static void readData(){ rwl.readLock().lock(); //用讀鎖鎖住 try { System.out.println(Thread.currentThread().getName() + " 准備讀"); Thread.sleep(new Random().nextInt(3000)); System.out.println(Thread.currentThread().getName() + " 讀完畢"); } catch (InterruptedException e) { e.printStackTrace(); }finally{ rwl.readLock().unlock(); } } }
用過Hibernate框架的朋友可能知道,Hibernate查詢數據庫有緩存機制,如果某個數據在內存中存在則可以並發的去讀取,如果緩存中沒有數據則需要互斥的去從數據庫取數據。
import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReentrantReadWriteLock; public class CacheDemo { private Map上面獲取數據的大概過程如下:cache = new HashMap (); public static void main(String[] args) { } private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); /** * 實現多個並發讀,互斥的寫 * @param key * @return */ public Object getData(String key){ rwl.readLock().lock(); Object value = null; try{ value = cache.get(key); if(value == null){ rwl.readLock().unlock(); //釋放讀鎖 rwl.writeLock().lock(); //添加寫鎖 try{ if(value == null){ //放置其他線程加載數據 value = "去數據庫查詢"; //這裡模擬從數據庫查詢 if(value == null){ //TODO 拋出異常 } } }finally{ rwl.writeLock().unlock(); } rwl.readLock().lock(); //鎖還給讀線程 } }finally{ rwl.readLock().unlock(); } return value; } }
1、獲取讀鎖,讀取數據
2、如果有數據則直接返回,並釋放讀鎖讓其他線程讀。
3、如果內存中沒有數據則從數據庫寫入內存,釋放讀鎖並添加寫鎖(這樣寫入數據就可以達到可以互斥)
4、讀入內存後釋放寫鎖並還回讀鎖(和後面的unlock()對應)
5、如果在添加寫鎖的時候同時有多個線程,則只能有其中一個線程搶到鎖,等擁有鎖的線程釋放寫鎖後,其他線程就會搶到寫鎖,但是此時數據已經寫入內存,則需要判斷內存數據是否為null如果不為null則直接釋放寫鎖。
使用adb shell procrank手機中的sh是經過精簡過的,有些手機可能沒有 procrank 命令,可以使用genymotion模擬器,或是自己安裝procra
對Android的啟動模式不是很了解,這裡記錄下簡單的理解內容以便日後查看。 Androi的四種啟動模式分別為:standard,singleTop,singl
前幾天做的一個仿To圈個人資料界面的實現效果下面是To圈的效果Gif圖:做這個東西其實也花了一下午的時間,一開始思路一直沒理清楚,就開始盲目的去做,結果反而事倍功半。以後
ContactPicker(選擇聯系人) 詳解 ContactPicker:用戶可以選擇一個聯系人. 1. 創建ContactP