Javaの同期の基本はsynchronizedなのだけど、synchronizedはブロックとして使わないといけないので使いづらい場合がある。ロックの取得と開放を同じメソッド内で行わなくてはいけないし、異なるロックを自由なタイミングで取得開放できない。
そこで使うのがLockなのだけど、とりあえずsynchronizedと同じ使い方でのサンプル。
真ん中から向こうは一両の「電車」しか同時に進めません。
Lockの実装クラスとしては、ReentrantLockが用意されています。
Lock lock = new ReentrantLock();
lockメソッドでロックを取得。同時にひとつのスレッドしかロックを得ることはできません。
lock.lock();
lockの開放はunlockを使います。unlockはfinallyブロックに書くほうがよいです。ただ、同じブロックで単純にlock/unlockするならsynchronizedのほうがいいと思います。
}finally{ lock.unlock(); }
ということでソース
import java.awt.*; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.swing.*; public class LockSample { private static Lock lock = new ReentrantLock(); public static void main(String args[]) { JFrame f = new JFrame("Lockサンプル"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new GridLayout(0, 1)); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); f.setBounds((screenSize.width-400)/2, (screenSize.height-300)/2, 400, 300); for(int i = 0; i < 10; ++i){ JTextField tf = new JTextField(); f.add(tf); Runner r = new Runner(); r.tf = tf; new Thread(r).start(); } f.setVisible(true); } private static class Runner implements Runnable{ JTextField tf; @Override public void run(){ try { String tr = "電車>"; for(int i = 0; i < 50; ++i){ tf.setText(tr); tr = " " + tr; Thread.sleep(50); } try{ lock.lock(); //ここから先は1つしか同時に進めない for(int i = 0; i < 50; ++i){ tf.setText(tr); tr = " " + tr; Thread.sleep(50); } }finally{ lock.unlock(); } } catch (InterruptedException ex) { } } } }