IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

JavaScript だってマルチスレッドくらいできるさ!

Rhino を使ってみた。

なんか spawn でスレッドが起動できる!便利!
spawn(function() {
    var i = 10;
    while(i--) print('hoge');
}); 
spawn(function() {
    var j = 10;
    while(j--) print('fuga');
}); 

結果

fugahoge

fuga
hogefuga

fuga
hogefuga

hoge
fuga
hogefuga

hogefuga

hogefuga

fuga
hoge
hoge
hoge
sync で同期を取る
print = sync(print); // <- これ

spawn(function() {
    var i = 10;
    while(i--) print('hoge');
}); 
spawn(function() {
    var j = 10;
    while(j--) print('fuga');
});

結果

fuga
hoge
fuga
hoge
fuga
hoge
fuga
hoge
fuga
hoge
fuga
hoge
fuga
hoge
fuga
hoge
fuga
hoge
fuga
hoge
sync はだいたいこんな感じになってた
// org/mozilla/javascript/tools/shell/Global.java
package org.mozilla.javascript.tools.shell
public class Global extends ImporterTopLevel {
    public static Object sync(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
        return new Synchronizer((Function)args[0]);
    }
}

// org/mozilla/javascript/Synchronizer.java
package org.mozilla.javascript;
public class Synchronizer extends Delegator {
    public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
        synchronized(thisObj) {
            return ((Function)obj).call(cx,scope,thisObj,args);
        }
    }
}

てことは sychronized(this) されるってことで sync を使うときは this に注意

で、 sync で BlockedQueue を作ろうと思ったんだけど

wait や notifyAll する方法がわかりません><

ということで sync は諦めて ReentrantLock を使うことにした
var lk = new java.util.concurrent.locks.ReentrantLock();
var queue = [];

queue._push = queue.push;
queue.push = function(o) {
  lk.lock();
  try {
    this._push(o);
  }
  finally {
    lk.unlock();
  }
};

queue._shift = queue.shift;
queue.push = function(o) {
  lk.lock();
  try {
    while (this.length == 0) {
      lk.unlock();
      lk.lock();
    }
    return this._shift();
  }
  finally {
    lk.unlock();
  }
};

できたー!

ってことで、これを使って doukaku.org のお題を説いてみた。
http://ja.doukaku.org/comment/3709/

まとめ

Rhino ドキュメント少ない><