私はAndroidの開発をやっているものの、もともとPHPerなのでJavaの知識はあんまりないです。だから、ちょっと難しい処理をやろうとするとどうしたらいいのかすぐにわからなくなってしまいます。それが、Javaの問題なのか、Android SDKの問題なのか、その区別も付かない場合があります。まぁそれはしゃあないとしても、地道にJavaの勉強をしていけば、Androidの開発にも役に立つのでやっていこうかと。
ちなみに本は結構持ってます。本コレクターなもんで。
でもJavaは2冊くらい…。もう何冊か必要に応じて買おうかと。
今日はスレッドの勉強をしました。
Androidでは非同期な動作はAsyncTaskが使えるので、そちらをガンガン使っててスレッドの使い方については学んでませんでした。なんか見る本でやり方が違ってたりするので、なんかよくわからんなーと思っていたのですが、どうもやり方が2種類あるようです。
- Threadクラスを継承するクラスを作成する
- Runnableインターフェースを実装する
どっちでもいいのか?と思っていたのですが、runメソッドをオーバーライドするだけならば、Runnableインターフェースを利用するほうが正しいようです。Threadクラスを利用する場合は、runメソッド以外もオーバーライドしてスレッドの基本的な動作を変えたいときだけ使用することが推奨されていると。なるほど。
Threadクラスを継承したほうが簡単ですが、おそらく余計なコストが発生するんでしょうね。
また、スレッドを使うとクラスのメンバ変数の状態がアクセスされたタイミングで上書きされてしまったりするので、排他制御も必要です。その場合はsynchronizedブロック、もしくはsynchronizedメソッドを使います。
以下は、synchronizedブロックの例
private int balance = 0; // メンバ変数 public void deposit(int money) { synchronized(this) { int total = balance + money; balance = total; } }
次に、synchronizedメソッドの例
private int balance = 0; // メンバ変数 synchronized public void deposit(int money) { int total = balance + money; balance = total; }
メソッドの処理全体をsynchrozed(this){…}で囲むのなら、synchronizedメソッドを使えということのようです。メンバ変数の排他制御のみ行えばいい訳だけど、わかりやすさはsyncronizedメソッドのほうがいいですね。代入以外が重たい処理ならば、synchronizedブロックを使うのがよさげ。
また、メンバ変数が複数のスレッドによってアクセスされる可能性があるのだったら、最初からメンバ変数自体に排他制御の印をつけることも可能のようです。それをvolatile変数というそうです。宣言するときに付けるだけ。
volatile private int balance;
明日は、スレッドの同期について学ぼうと思います。
Pingback: Java: スレッドの制御を学ぶ(優先度) | 自転車で通勤しましょ♪ブログ