編輯:關於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則直接釋放寫鎖。
Android procrank查看內存使用情況
使用adb shell procrank手機中的sh是經過精簡過的,有些手機可能沒有 procrank 命令,可以使用genymotion模擬器,或是自己安裝procra
Android的四種啟動模式
對Android的啟動模式不是很了解,這裡記錄下簡單的理解內容以便日後查看。 Androi的四種啟動模式分別為:standard,singleTop,singl
Android模仿To圈兒個人資料界面層疊淡入淡出顯示效果
前幾天做的一個仿To圈個人資料界面的實現效果下面是To圈的效果Gif圖:做這個東西其實也花了一下午的時間,一開始思路一直沒理清楚,就開始盲目的去做,結果反而事倍功半。以後
Android - ContactPicker(選擇聯系人) 詳解
ContactPicker(選擇聯系人) 詳解 ContactPicker:用戶可以選擇一個聯系人. 1. 創建ContactP