As a matter of fact, the Java memory model is such that a modification
to a variable in one thread may not immediately be visible to other threads. Actually, it
may never be visible. Consider the code in Listing 5–11: if one thread calls
MyClass.loop(), and at some point in the future another thread calls
Myclass.setValue(100), the first thread may still not terminate; may carry on looping
forever and always print out a value other than 100, simply because of the Java
language’s memory model.
Listing 5–11. Java Memory Model Impact
public class MyClass {
private static final String TAG = "MyClass";
private static int mValue = 0;
public static void setValue(int n) {
mValue = n;
}
public static void loop () {
while (mValue != 100) {
try {
Log.i(TAG, “Value is ” + mValue);
Thread.sleep(1000);
} catch (Exception e) {
// ignored
}
}
}
}
You have two options to fix that:
Use the synchronized keyword, as shown in Listing 5–12.
Use the volatile keyword, as shown in Listing 5–13.
Listing 5–12. Adding the Synchronized Keyword
public class MyClass {
private static final String TAG = "MyClass";
private static int mValue = 0;
public static synchronized void setValue(int n) {
mValue = n;
}
public static synchronized int getValue() {
return mValue;
}
public static void loop () {
int value;
while ((value = getValue()) != 100) {
try {
Log.i(TAG, “Value is ” + value);
Thread.sleep(1000);
} catch (Exception e) {
// ignored
}
}
}
}
Listing 5–13. Adding the Volatile Keyword
public class MyClass {
private static final String TAG = "MyClass";
private static volatile int mValue = 0; // we add the volatile keyword and remove
the synchronize keyword
public static void setValue(int n) {
mValue = n; // you’d still have to use synchronized if that statement were mValue += n (not atomic)
}
public static void loop () {
while (mValue != 100) {
try {
Log.i(TAG, “Value is ” + mValue);
Thread.sleep(1000);
} catch (Exception e) {
// ignored
}
}
}
}
2015年4月13日 星期一
2015年4月12日 星期日
[Android] Handlers and Loopers
Android defines two classes in the android.os package that will often be the
cornerstones of the interthread communication in your multithreaded applications:
Handler
Looper
While creating an AsyncTask object hides the Handler and Looper details from you, in
some cases you need to use handlers and loopers explicitly, for example when you need
to post a Runnable to a thread other than the main thread.
you use a
Handler object to post a Runnable in a Looper’s message queue. Your application’s main
thread already has a message queue, so you don’t have to create one explicitly.
However, the threads you create do not come automatically with a message queue and
message loop, so you would have to create one yourself if needed. Listing 5-8 shows
how you can create a thread with a Looper.
Listing 5–8
public class MyThread extends Thread {
private static final String TAG = “MyThread”;
private Handler mHandler;
public MyThread(String name) {
super(name);
}
public Handler getHandler() {
return mHandler;
}
@Override
public void run() {
Looper.prepare(); // binds a looper to this thread
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// process messages here
}
}
};
// the handler is bound to this thread’s looper
Looper.loop(); // don’t forget to call loop() to start the message loop
// loop() won’t return until the loop is stopped (e.g., when Looper.quit() is called)
}
}
Android provides an easier way to work with looper threads with the HandlerThread
class, which also makes it easier to avoid the potential race condition mentioned in
Listing 5–8, where getHandler() may still return null even after the thread has been
started. Listing 5–9 shows how to use the HandlerThread class.
Listing 5–9. Using the HandlerThread Class
public class MyHandlerThread extends HandlerThread {
private static final String TAG = "MyHandlerThread";
private Handler mHandler;
public MyHandlerThread(String name) {
super(name);
}
public Handler getHandler() {
return mHandler;
}
@Override
public void start() {
super.start();
Looper looper = getLooper(); // will block until thread’s Looper object is initialized
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// process messages here
}
}
};
}
}
cornerstones of the interthread communication in your multithreaded applications:
Handler
Looper
While creating an AsyncTask object hides the Handler and Looper details from you, in
some cases you need to use handlers and loopers explicitly, for example when you need
to post a Runnable to a thread other than the main thread.
you use a
Handler object to post a Runnable in a Looper’s message queue. Your application’s main
thread already has a message queue, so you don’t have to create one explicitly.
However, the threads you create do not come automatically with a message queue and
message loop, so you would have to create one yourself if needed. Listing 5-8 shows
how you can create a thread with a Looper.
Listing 5–8
public class MyThread extends Thread {
private static final String TAG = “MyThread”;
private Handler mHandler;
public MyThread(String name) {
super(name);
}
public Handler getHandler() {
return mHandler;
}
@Override
public void run() {
Looper.prepare(); // binds a looper to this thread
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// process messages here
}
}
};
// the handler is bound to this thread’s looper
Looper.loop(); // don’t forget to call loop() to start the message loop
// loop() won’t return until the loop is stopped (e.g., when Looper.quit() is called)
}
}
Android provides an easier way to work with looper threads with the HandlerThread
class, which also makes it easier to avoid the potential race condition mentioned in
Listing 5–8, where getHandler() may still return null even after the thread has been
started. Listing 5–9 shows how to use the HandlerThread class.
Listing 5–9. Using the HandlerThread Class
public class MyHandlerThread extends HandlerThread {
private static final String TAG = "MyHandlerThread";
private Handler mHandler;
public MyHandlerThread(String name) {
super(name);
}
public Handler getHandler() {
return mHandler;
}
@Override
public void start() {
super.start();
Looper looper = getLooper(); // will block until thread’s Looper object is initialized
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// process messages here
}
}
};
}
}
2015年4月7日 星期二
[Android][Java] Java define 4 reference type
Strong
Soft
Weak
Phantom
it is important to avoid memory leak
Android’s LruCache uses strong references
Soft
Weak
Phantom
it is important to avoid memory leak
Android’s LruCache uses strong references
2015年3月26日 星期四
[Design Partern] Strategy pattern case 1: Android load NDK library
在 Android 的開發中使用 NDK 最佳化的時候,可能會因為平台的差異,導致 native code 無法執行,這時候必須提供 Java 版本的 solution。
Design Pattern 裡面有一個Strategy pattern,他的特性如下:
In computer programming, the strategy pattern (also known as the policy pattern) is a software design pattern that enables an algorithm's behavior to be selected at runtime. The strategy pattern
1. defines a family of algorithms,
2. encapsulates each algorithm, and
3. makes the algorithms interchangeable within that family.
載入 native library 的時機點也是在 runtime,剛好符合 Startegy pattern 的 case:
載入 native library 的時機點也是在 runtime,剛好符合 Startegy pattern 的 case:
例子如下:
2015年3月20日 星期五
[Performance] Fibonacci演算法探討演算法最佳解
2014年12月29日 星期一
[Android] 可以 count Jar 檔案的 method 數量的 script
dx --dex --output=temp.dex $1
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'
rm temp.dex
dx 要用
/home/charles_lo/Program/adt-bundle-linux-x86_64-20140702/sdk/build-tools/21.1.1
不要用 apt-get 去安裝
實測效果
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'
rm temp.dex
dx 要用
/home/charles_lo/Program/adt-bundle-linux-x86_64-20140702/sdk/build-tools/21.1.1
不要用 apt-get 去安裝
實測效果
2014年12月12日 星期五
[Android] Eclipse ADT budle download link
最近eclipse ADT bundle download link 官方網站已經找不到了,所以備份一下連結
linux 64 bit vm: http://dl.google.com/android/adt/adt-bundle-linux-x86_64-20140702.zip linux 32 bit vm: http://dl.google.com/android/adt/adt-bundle-linux-x86-20140702.zip mac: http://dl.google.com/android/adt/adt-bundle-mac-x86_64-20140702.zip win32: http://dl.google.com/android/adt/adt-bundle-windows-x86-20140702.zip win64: http://dl.google.com/android/adt/adt-bundle-windows-x86_64-20140702.zip 還有一個更新失敗的 issue 連結 https://code.google.com/p/android/issues/detail?id=73102
訂閱:
文章 (Atom)