ว่าด้วยเรื่อง “Runnable กับ Callable” ใน Java

Phayao Boonon
2 min readOct 14, 2018

--

ใน Multi-thread application (Concurrecy application) ใน Java มี 2 วิธีที่จะสร้าง Thread วิธีที่หนึ่งคือ extends คลาส Thread และอีกวิธีคือ implementRunnable แต่อย่างไรก็ตามสิ่งที่ขาดไปของ Runnable คือการ return ผลลัพย์ออกมาเมื่อมันถูก terminate หรือรันจบแล้ว เพื่อที่จะแก้ไขปัญหานี้จึงมี Callable ดังนั้นในบทความนี้จึงจะมาดูว่าทั้งสอง interface มีความแตกต่างกันอย่างไรบ้าง

Execution Mechanism

ทั้ง 2 Interface ออกแบบให้แทน Task ที่สามารถ execute ด้วยหลายๆ Thread ซึ่งสามารถใช้คลาส Thread แต่ทว่า Callable ไม่สามารถใช้กับคลาส Thread เพื่อสร้าง Thread ได้

Runnable

Runnable interface เป็น functional interface และมี method เดียวคือ run() ซึ่งไม่รับ parameters และไม่มีการ return ค่าใดๆ

ใช้ในสถานการณ์ที่ไม่ต้องการจะรับ result ใดๆ จากการทำงานของ thread ดังนี้

public interface Runnable {
public void run():
}

ตัวอย่างเช่น

public class RunnableDemo implements Runnable {
private Object result = null;

@Override
public void
run() {
Random generator = new Random();
Integer randomNumber = generator.nextInt(5);

try {
Thread.sleep(randomNumber * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

result = randomNumber;

synchronized (this) {
notifyAll();
}
}

public synchronized Object get() throws InterruptedException {
while (result == null) {
wait();
}
return result;
}
}

ซึ่งสามารถรันด้วยการสร้าง Thread และเรียก get() เพื่อแสดงผลที่ console

public class RunnableDemoTest {
public static void main(String[] args) throws Exception {
RunnableDemo[] randomeTasks = new RunnableDemo[5];

for(int i = 0; i < 5; i++) {
randomeTasks[i] = new RunnableDemo();
Thread t = new Thread(randomeTasks[i]);
t.start();
}

for(int i = 0; i < 5; i++) {
System.out.println(randomeTasks[i].get());
}
}
}

จะได้ผลลัพธ์เป็นค่า random 5 ค่าแสดงบน console

3
2
0
4
2
Process finished with exit code 0

Callable

Callable interface เป็น generic interface ที่มี method เดียวคือ call() ซึ่งจะไม่รับ parameters ใดๆ และจะ return เป็น generic typeV และมีการ throw exception

public interface Callable<V> {
V call() throws Exception;
}

ตัวอย่างเช่น สร้างคลาส CallableDemo ที่ implement Callable interface โดยที่จะ return เป็นค่า random 1– 4 และ throws Exception

public class CallableDemo implements Callable<Integer> {
@Override
public
Integer call() throws Exception {
Random generator = new Random();
Integer randomNumber = generator.nextInt(5);

Thread.sleep(randomNumber * 1000);

return randomNumber;
}
}

ซึ่งจะต้องใช้คลาส FuturTask มาสร้าง Thread เพื่อรัน CallableDemo เนื่องจากว่า Callable ไม่สามารถใช้สร้าง Thread ได้โดยตรง เมือ method call() ทำงานเสร็จแล้วก็จะเก็บผลลัพธ์ไว้ใน Future object และเรียก get() เพื่อแสดงผลที่ console

public class CallableDemoTest {
public static void main(String[] args) throws Exception {
FutureTask[] randomNumberTasks = new FutureTask[5];

for(int i = 0; i < 5; i++) {
Callable callable = new CallableDemo();
randomNumberTasks[i] = new FutureTask(callable);
Thread t = new Thread(randomNumberTasks[i]);
t.start();
}

for(int i = 0; i < 5; i++) {
System.out.println(randomNumberTasks[i].get());
}
}
}

จะได้ผลลัพธ์เป็นค่า random 5 ค่าแสดงบน console

4
4
3
3
0
Process finished with exit code 0

จะเห็นได้ว่า Callable จะเหมือนกับ Runnable แต่จะแตกต่างกันที่ Callable จะไม่สามารถสร้าง Thread ได้โดยตรง มีการ return ค่าออกมาตาม generic type และสามารถ throw Exception ออกมาได้ แต่ Runnable สามารถสร้าง Thread ได้โดยตรง แต่จะไม่มีการ return ค่าออกมา และไม่สามารถ throw Exception ได้ สามาเลือกใช้ได้ตามความต้องการ

อ้างอิง

--

--

Phayao Boonon

Software Engineer 👨🏻‍💻 Stay Hungry Stay Foolish