วันพฤหัสบดีที่ 9 ตุลาคม พ.ศ. 2551

ทดลองใช้ JSR166y

พอดีไปเห็นบทความเกี่ยวกับ JSR166y ที่นี่ http://groovy.dzone.com/news/concurrency-jsr-166y-meets-gro

โดยเป้าหมายหลักของ JSR166y คือ lightweight task framework สำหรับ Java Platform ซึ่งใช้แนวคิดของ Fork and Join Framework เพื่อนำมาแก้ไขปัญหาการใช้งาน Thread ในระบบแบบขนาน เนื่องจาก Thread นั้นกินทรัพยากรของระบบมากจนเกินไป

๋JSR166y นี้เป็น library ตัวใหม่ที่วางแผนไว้ว่าจะเพิ่มเข้าไปใน JDK 7 ครับ

สำหรับ library นั้นสามารถ Download ได้ที่นี่ http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166y.jar

ส่วน JavaDoc ก็ที่นี่ครับ http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/overview-summary.html


ผมลองทำการทดสอบใช้งานดังนี้
- ทำ application เพื่ออ่าน Rss Feed จากหลายๆ เว็บ ดังนี้

Environment ที่ใช้ทดสอบ
- Windows XP
- JDK 6


String[] url = {
"http://www.grails66.com/blog/feed/",
"http://www.rails66.com/blog/feed/",
"http://www.ajax66.com/blog/feed/",
"http://www.seam66.com/blog/?feed=rss2",
"http://www.ofbiz66.com/blog/?feed=rss2"
};

ForkJoinExecutor fje = ParallelArray.defaultExecutor();
ParallelArray p = ParallelArray.createFromCopy(url, fje);
p.replaceWithMapping(new RssFeed());
System.out.println(p.asList());


สร้าง class RssFeed สำหรับการทำงานในแต่ละ process ที่แตกออกมา ( Fork ) ดังนี้

class RssFeed implements Op {

@Override
public String op(String url) {
System.out.println(System.currentTimeMillis() + " : " + url);
return getData(url);
}
}

เมื่อทำการ run แล้วจะเห้นได้ว่าจะไม่ได้ทำการแบบ sequential เลย จะทำงานแบบ parallel ครับ ตรงนี้ทำงานดูดีครับ

หรืออาจจะกำหนด Pool ของ ForkJoin process ได้เองดังนี้

ForkJoinPool pool = new ForkJoinPool(3); // กำหนดเป็น 3
ParallelArray p = ParallelArray.createFromCopy(url, pool);

ทดสอบ run ก็จะได้ผลอีกแบบครับ


เอกสารเพิ่มเติม
http://groovy.dzone.com/news/concurrency-jsr-166y-meets-gro

ป้องกันการ run process แบบไม่สิ้นสุดใน Java

วันนี้ทำการทดสอบ migrate data process ซึ่งจะมีบาง process ทำการ run process ผ่าน java.lang.Process

โดยปัญหาที่พบคือ อาจจะมีบาง process ที่ทำงานไม่จบสักที [ ไม่มี signal ออกมาจาก process นั้น ]

ส่วน code ที่เป้นปัญหาคือ มัน
while( true ) {
try {
int process_status = process.waitFor();
break;
} catch( InterruptedException e ) {
}
}

ปัญหามันเกิดขึ้นมาเมื่อ process ไม่มี signal อะไรออกมา

ดังนั้น สามารถแก้ปัญหาได้โดยการใช้ Timer มาช่วย จะกำหนด timeout ได้ ดังนี้

Timer timer = new Timer();
timer.schedule(new InterruptProcess(Thread.currentThread()), 5000);
try {
exitStatus = proc.waitFor();
}
catch (InterruptedException e) {
proc.destroy();
}
finally {
timer.cancel();
}

และ Class InterruptProcess ซึ่งจะ extends มาจาก timerTask ดังนี้

class InterruptProcess
extends TimerTask {
Thread target = null;
InterruptProcess(Thread target) {
this.target = target;
}

/**
* run
*/
public void run() {
target.interrupt();
System.out.print("-|Run Interrupt|-");
}

}

จากตัวอย่าง ผมทำการกำหนด timeout = 5 วินาที ดังนั้นถ้า process มีเวลาทำงานมากที่สุดคือ 5 วินาทีเท่านั้น ส่วน process ที่ run เสร็จเร็วก็ไม่มีปัญหาอะไร