独習Java第9章 マルチスレッドプログラミング(9.5 2回目)

前回やって意味が分からなかったので再度やってみることに。ただし全然わかってない気がする……
環境:MacOS 10.6.5 / Oracle(Sun) JDK6 update22

書いてみる

// Sync.java
class Flag
{
  public static boolean flag = true;
}

class IntBox
{
  public synchronized void add(int value)
  {
    this._value += value;

    notify();
    Flag.flag = true;
  }

  public synchronized int getValue()
  {
    return this._value;
  }

  private int _value = 0;
}

class ThreadEx extends Thread
{
  ThreadEx(String name, IntBox intBox)
  {
    this._name = name;
    this._intBox = intBox;
  }

  public void run()
  {
    while (!Flag.flag)
    {
      try
      {
        wait();
      }
      catch (InterruptedException e)
      {
        e.printStackTrace();
      }
    }

    Flag.flag = false;

    for (int i = 0; i < 50; i++)
    {
      this._intBox.add(1);
      System.out.println(this._name + ": " + this._intBox.getValue());
    }
  }

  private String _name;
  private IntBox _intBox;
}

class Sync
{
  public static void main(String args[])
  {
    IntBox intbox = new IntBox();
    Thread t[] = new ThreadEx[THREAD_COUNT];

    for (int i = 0; i < THREAD_COUNT; i++)
    {
      t[i] = new ThreadEx("t" + i, intbox);
      t[i].start();
    }

    for (int i = 0; i < THREAD_COUNT; i++)
    {
      try
      {
        t[i].join();
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
    }

    System.out.println("end");
  }

  private final static int THREAD_COUNT = 50;
}

睡魔と戦いつつJavaに毒づきながら書いたためひどいコードに。

実行してみる

$ javac Sync.java
$ java Sync
t0: 1
t0: 2
t0: 3
(略)
t30: 2469
t30: 2477
t13: 2476
t30: 2478
t13: 2479
t13: 2480
(略)
t13: 2498
t13: 2499
t13: 2500
end

t0〜t49まできれいに並んでくれないのは、JVMがそういう順番でスレッドを動かしてるからなのかな。


うーんと、要するにスレッドが動いていて、別のスレッドと競合(?)する可能性がある場合に何かしらのフラグでwait()して、触れるスレッドは触った後にnotify()を呼ぶことで衝突を回避できる…… ってことなのかな。
wait(), notify()は古いのでconcurrent使いましょう、とかいう記事を見たりとかしてもう半分どうでもよくなってきてるというのが正直なところ。


9章終わり。スレッドはもっと鍛えないとかなー……
それともスレッドを使うときはErlangとかScalaに逃げる…なんて。無理か。