Successfully reported this slideshow.

Node.js - JavaScript Thread Programming

3,258 views

Published on

Published in: Technology, Health & Medicine
  • Be the first to comment

Node.js - JavaScript Thread Programming

  1. 1. Node.js で学ぶマルチスレッドプログラミング入門<br />サイボウズ・ラボ / Shibuya.pm<br />竹迫 良範 @TAKESAKO<br />
  2. 2. 2009/04/06<br />Cybozu University<br />2<br />JavaScript<br />
  3. 3. sleep のない言語 JavaScript<br />どうやって実現するか?<br />function sleep(msec) { // CPU_100%<br /> var t = (new Date()).getTime()-(-msec); <br /> while ( (new Date()).getTime() < t ) {} <br />}<br />function sleep(msec) { <br /> // LiveConnect<br /> Packages.java.lang.Thread.sleep(msec); <br />}<br />
  4. 4. クロスブラウザで sleep を実現(無理矢理)<br />function sleep(msec) { <br /> try { // for IE<br />window.showModalDialog(<br /> "javascript:document.write('<script>"<br /> + "window.setTimeout(function(){window.close()},"<br /> + msec + ");<"/script>');"); <br /> } catch (e) { <br /> try { // for Firefox, Opera with LiveConnect<br />Packages.java.lang.Thread.sleep(msec); <br /> } catch (e) { // for Safari and others <br />var limit = (new Date()).getTime() - (-msec); <br /> while ((new Date()).getTime() < limit) {} <br /> } <br /> } <br />} <br />
  5. 5. 1秒ごとに表示したい(よくある間違い)<br /><script><br />function sleep(msec) {<br />var t = (new Date()).getTime() - (-msec);<br /> while ( (new Date()).getTime() < t );<br />}<br />function init() {<br />var body = document.body;<br /> sleep(1000);<br />body.innerHTML += "<h1>Hello!</h1>";<br /> sleep(1000);<br />body.innerHTML += "<h2>Hello?</h2>";<br /> sleep(1000);<br />body.innerHTML += "<h3>Hello!?</h3>";<br />};<br /></script><br /><body onload="init()"></body><br />
  6. 6. 問題1:sleep している間 CPU_100% (><)<br />
  7. 7. 問題2:3秒後にまとめて表示される<br />
  8. 8. setTimeoutで1秒ごとに表示する(正解)<br /><script><br />setTimeout(function(){<br />var body = document.body;<br />body.innerHTML += "<h1>Hello!</h1>";<br />setTimeout(function(){<br />body.innerHTML += "<h2>Hello?</h2>";<br />setTimeout(function(){<br />body.innerHTML += "<h3>Hello!?</h3>";<br /> }, 1000);<br /> }, 1000);<br />}, 1000);<br /></script><br />
  9. 9. setTimeout.html – シングルスレッド+遅延<br />
  10. 10. 2009/04/06<br />Cybozu University<br />10<br /> }, 1000);<br /> }, 1000);<br /> }, 1000);<br /> }, 1000);<br />}, 1000);<br />
  11. 11. 2009/04/06<br />Cybozu University<br />11<br /> });<br /> });<br /> });<br /> });<br />});<br />
  12. 12. yield<br />
  13. 13. yield で1秒ごとに表示<br /><!DOCTYPE html><br /><title>Firefox2.0+ only</title><br /><script type="application/javascript;version=1.7"><br />(function(g){var f=arguments.callee;setTimeout(<br /> function(){f(g)},g.next())})((function(){<br /> yield (1000);<br />document.body.innerHTML += "<h1>Hello!</h1>";<br /> yield (1000);<br />document.body.innerHTML += "<h2>Hello?</h2>";<br /> yield (1000);<br />document.body.innerHTML += "<h3>Hello!?</h3>";<br />})());<br /></script><br />
  14. 14. yield.html– 疑似マルチタスク処理<br />
  15. 15. やりたいこと = 細かく setTimeoutを呼ぶ<br />// こんな風に書けたらいいなぁ(><)<br /> for (var i = 0; i < 10000000; i++) {<br /> // すん<br /> //  ごく<br /> //  重たい<br /> //  処理<br /> //   ・・・<br />setTimeout(次の行, 0); // ブラウザに処理を戻す<br /> // でもループの中は繰り返したい<br /> }<br />  // 終了<br />
  16. 16. JavaScript 1.7<br />(Firefox 2.0+)<br />
  17. 17. yield を含む関数は Generator になる<br />function generator() {<br /> for (var i = 1; i <= 1000; i++) {<br /> document.title = i;<br /> yield;<br /> }<br />}<br />var g = generator(); // [object Generator]<br />// まだ document.title は変更されない<br />
  18. 18. Generator#nextで次の yield まで実行戻る<br />function generator() {<br /> for (var i = 1; i <= 1000; i++) {<br /> document.title = i;<br /> yield;<br /> }<br />}<br />var g = generator(); // [object Generator]<br />g.next(); // document.title = 1;<br />g.next(); // document.title = 2;<br />g.next(); // document.title = 3;<br />
  19. 19. uncaught exception: [object StopIteration]<br />function generator() {<br /> for (var i = 1; i <= 1000; i++) {<br /> document.title = i;<br /> yield;<br /> }<br />}<br />var g = generator();<br />for (var j = 1; j <= 998; j++) { g.next() }<br />g.next(); // document.title = 999;<br />g.next(); // document.title = 1000;<br />g.next(); // Error: uncaught exception: // [object StopIteration]<br />
  20. 20. Generator#close<br />function generator() {<br /> for (var i = 1; i <= 1000; i++) {<br /> document.title = i;<br /> yield;<br /> }<br />}<br />var g = generator();<br />for (var j = 1; j <= 998; j++) { g.next() }<br />g.next(); // document.title = 999;<br />g.next(); // document.title = 1000;<br />g.close();<br />
  21. 21. yield の引数が next() の戻り値になる<br />function generator() {<br /> for (var i = 1; i <= 1000; i++) {<br /> document.title = i;<br /> yield (i);<br /> }<br />}<br />var g = generator();<br />var r;<br />r = g.next(); // r = 1;<br />r = g.next(); // r = 2;<br />r = g.next(); // r = 3;<br />
  22. 22. next() の戻り値をチェックしてきちんと終了<br />function generator() {<br /> for (var i = 1; i <= 1000; i++) {<br />document.title = i;<br /> yield (i);<br /> }<br /> yield (-1); // 終了条件<br />}<br />var g = generator();<br />var r;<br />do { r = g.next() } while (r > 0); // 1...1000<br />g.close();<br />
  23. 23. 巨大ループ中で setTimeout(f, 0) が呼べる!<br />function generator() {<br /> for (vari = 1; i <= 1000; i++) {<br />document.title = i;<br /> yield true;<br /> }<br /> yield false;<br />}<br />function driveGenerator(g) {<br /> if (g.next()) { //  yield true?<br />var f = function(){ driveGenerator(g) };<br />setTimeout(f, 0); <br />} else {<br />g.close(); //  yield false<br /> }<br />}<br />driveGenerator( generator() );<br />
  24. 24. yield + setTimeoutイディオムが完成<br />(function(g){var f=arguments.callee;var t=g.next();<br /> (t<0) ? g.close():setTimeout(function(){f(g)},t)})<br />((function(){<br /> for (vari = 0; i < 10000; i++) {<br />document.title = i; // 重たい処理<br /> yield (0); // ブラウザに一旦処理を戻す(setTimeout)<br /> }<br /> yield (-1); // 終了<br />})());<br />
  25. 25. yield すごい !<br />
  26. 26.  でも…<br /> Firefoxでしか…<br />
  27. 27. JavaScript1.7 の指定をしないと yield 動かない<br /><script type="application/javascript;version=1.7"><br />(function(g){var f=arguments.callee;var t=g.next();<br /> (t<0) ? g.close():setTimeout(function(){f(g)},t)})<br />((function(){<br /> for (vari = 0; i < 10000; i++) {<br />document.title = i; // 重たい処理<br /> yield (0); // ブラウザに一旦処理を戻す(setTimeout)<br /> }<br /> yield (-1); // 終了<br />})());<br /></script><br />
  28. 28. 28<br /><br />
  29. 29. HTML5 関連<br />Web Workers<br />
  30. 30. HTML5 Web Workers API<br />main.html<br />worker.js<br />(1) var worker = new Worker(“worker.js”);<br />ワーカースレッドの作成<br />(2) worker.postMessage(”hello”);<br />(3) onmessage = function(e) {<br />var result = e.data + ”!”;<br />(4) postMessage(result);<br />(5) worker.onmessage = function(e) {<br /> // DOM 更新処理<br />window.alert(e.data);<br />
  31. 31. ワーカスレッドを呼び出す UIスレッド<br />worker.html<br /><title>HTML5 Web Workers</title><br /><script><br />var worker = new Worker("worker.js");<br />worker.onmessage = function(e){<br />document.body.innerHTML += e.data;<br />}<br />worker.postMessage("hello");<br /></script><br />
  32. 32. ワーカスレッドの定義(重たい処理を分離)<br />worker.js<br />function sleep(msec) {<br />var t = (new Date()).getTime() - (-msec);<br /> while ( (new Date()).getTime() < t );<br />}<br />//↓ワーカ側でメッセージを受信したときの処理<br />onmessage = function(e) {<br /> sleep(1000);<br />postMessage("<h1>" + e.data + "!</h1>");<br />}<br />
  33. 33. Web Workers のセキュリティ<br />UIスレッド<br />ワーカスレッド<br />window.document.write(“hoge”)<br />Workerスレッドからは<br />wndowオブジェクトに<br />触れない!<br />CPU_100%でも<br />ブラウザ固まらない!<br />
  34. 34. Firefox, Safari, Chrome で動作<br />
  35. 35. 2009/04/06<br />Cybozu University<br />35<br />Node.js<br />拡張<br />できる?<br />
  36. 36. 2009/04/06<br />Cybozu University<br />36<br />
  37. 37. 2009/04/06<br />Cybozu University<br />37<br />
  38. 38. v8-juice<br />
  39. 39. jsthread.sourceforge.net<br />
  40. 40. 40<br /><br />

×