Chap10

  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Chap10 as PDF for free.

More details

  • Words: 764
  • Pages: 10
MultiThread

Modern Programming Languages

10

โปรแกรมแบบมัลติเธรด (MultiThread) 10.1

โปรแกรมแบบมัลติเธรด

คุณสมบัติเดนอีกอยางหนึ่งของภาษาจาวาคือ ความสามารถในการพัฒนาโปรแกรมแบบมัลติเธรด คือ สามารถทํางานหลายงานพรอมกันได ซึ่งอาศัยหลักการทํางานแบบมัลติทาสกิ้ง (MultiTasking) โดยระบบมัลติ ทาสกิ้งอนุญาติใหผูใชสามารถสงโปรแกรมใหระบบปฏิบัติการทํางานไดมากกวาหนึ่งโปรแกรมพรอมกัน ซึ่งแตละ โปรแกรมที่รันอยูในระบบปฏิบัติการจะสราง process ขึ้นมา และในระบบปฏิบัติการแบบมัลติทาสกิ้งจะมี process หลายๆ process เขาคิวรอการทํางาน โดยระบบปฏิบัติการจะกําหนดลําดับของการทํางานของ process เอง ในโปรแกรมแบบมัลติเธรดจะเปนการทํางานพรอมกันโดยที่แตละงาน (process) จะเรียกวา เธรด (thread) ซึ่งแตกตางจาก process ที่ทํางานภายใตระบบปฏิบัติการแบบมัลติทาสกิ้งตรงที่ ในแตละเธรดจะทํางาน อยางเปนอิสระตอกัน ในแตละ thread มีสวนที่ใชขอมูลรวมกัน (share variable) โปรแกรมภาษาจาวาสามารถกําหนดการทํางานเปนแบบเธรดไดโดยการสรางอบบเจกตของคลาสใดๆ ใหทํางานแบบเธรด ซึ่งจะทําใหสามารถสรางรันโปรแกรมของออบเจกตแบบเธรดหลายๆออบเจกตไดพรอมกัน โดยภาษาจาวาจะมีตัวจัดตารางเวลา(Thread Scheduler) ของออบเจกตแบบเธรด เพื่อจัดลําดับการทํางานของ แตละออบเจกตแบบเธรด 10.2

การสรางคลาสแบบเธรด (Thread)

คลาสแบบเธรด คือคลาสที่สืบทอดคุณสมบัติจากคลาส Thread หรือคลาสที่ implements อินเตอรเฟส Runnable ในการสรางทั้งสองรูปแบบจะตองมีการ overriding เมธอด run() เพื่อระบุการทํางานแบบ thread ที่ ตองการออบเจกตที่ถูกสรางขึ้นจากคลาสแบบ Thread เรียกวา ออบเจกตแบบ Runnable interface Runnable void run()

implements

คลาสแบบ thread void run()

ถาไมมีเมธอด run() คอมไพลไมผาน ***ฉะนั้นตองมีการ overriding เมธอด run()

Thread void run()

คลาสแบบ thread

extends

void run()

เพื่อระบุการทํางานแบบ thread ในการสรางทั้ง 2 แบบ ถาไมมีเมธอด run() คอมไพลผาน แตไมระบุการทํางาน

[email protected]

1/10

MultiThread

Modern Programming Languages

10.2.1 การ extends คลาส Thread

รูปแบบ

โดยที่เมธอด run() จะประกอบดวยการทํางานที่มีลักษณะแบบเธรด การสรางและเริ่มตนการทํางานของออบเจกตเธรด ทําไดดังนี้

• •

ในบรรทัดที่ 1 และ 2 เปนการสรางออบเจกตชนิด Thread ชื่อ objName1 และ objName2 ตามลําดับ ในบรรทัดที่ 3 และ 4 เปนการเรียกใชงานเมธอด start() เพื่อสั่งใหออบเจกตชนิด Thread เริ่ม ทํางาน โดยการทํางานจะไปเรียกการทํางานที่เมธอด run() โดยการทํางานจะเกิดขึ้นพรอมๆกัน ดังรูปดานลาง objName1.start() objName2.start()



หากออบเจกตชนิด Thread ไมมีการเรียกใชงานเมธอด start() จะไมเกิดการทํางานแบบเธรด เชน เมื่อเรียกใชคําสั่งดังนี้ o o



objName1.run(); objName2.run();

จะเปนการทํางานตามคําสั่ง คือ เมื่อทําคําสั่ง objName1.run() เสร็จแลว จึงไปทํางานตอที่คําสั่ง objName2.run(); ดังรูปดานลาง objName1.run() objName2.run()

[email protected]

2/10

MultiThread

Modern Programming Languages

ตัวอยาง การสรางออบเจกตชนิด Thread ดวยการ extends คลาส Thread

ผลลัพธที่ไดจะไมเหมือนกันเสมอไป ตองลองรันโปรแกรมเพื่อดูผลที่เกิดขึ้น การทํางานในแตละเธรดจะ เกิดขึ้นพรอมๆ กัน 10.2.2 การ implements อินเตอรเฟส Runnable

รูปแบบ

ในการสรางลักษณะนี้จะตองมีการสรางออบเจกตของคลาส Thread กอน โดยคลาส Thread มีคอน สตรัคเตอร ทําการรับพารามิเตอรออบเจกตของ Runnable มีรูปแบบดังนี้

[email protected]

3/10

MultiThread

Modern Programming Languages

การสรางและเริ่มตนการทํางาน thread ทําไดดังนี้

• • •

ในบรรทัดที่ 1 และ 2 เปนการสรางออบเจกตชนิด Runnable ชื่อ objRunnable1 และ objRunnable2 ตามลําดับ ในบรรทัดที่ 3 และ 4 การสรางออบเจกตชนิด Thread โดยคอนสตรัคเตอรของคลาส Thread ทํา การรับพารามิเตอรออบเจกตของ Runnable ที่ไดสรางไวแลว ในบรรทัดที่ 5 และ 6 เปนการเรียกใชงานเมธอด start() เพื่อสั่งใหออบเจกตชนิด Thread เริ่ม ทํางาน โดยการทํางานจะไปเรียกการทํางานที่เมธอด run() ซึ่งเมธอด run() นี้อยูในคลาสซึ่ง implements อินเตอรเฟส Runnable โดยการทํางานจะเกิดขึ้นพรอมๆกัน

ตัวอยาง การสรางออบเจกตชนิด Thread ดวยการ implements อินเตอรเฟส Runnable โดยการทํา การปรับปรุงจากตัวอยางขางตน

[email protected]

4/10

MultiThread

Modern Programming Languages

การสรางคลาสแบบเธรดทั้งสองวิธีมีขอดีตางกันดังนี้ • การสรางคลาสโดยการสืบทอดคลาสที่ชื่อ Thread จะเปนการเขียนโปรแกรมที่สั้นกวา • การสรางคลาสโดย implement อินเตอรเฟส Runnable จะมีหลักการเชิงออปเจ็คที่ดีกวา เนื่องจาก คลาสดังกลาวไมใชคลาสที่สืบทอดมาจาก Thread โดยตรง นอกจากนี้ยังทําใหการเขียนโปรแกรมมี รูปแบบเดี่ยวกันเสมอ เพราะคลาสในจาวาจะสืบทอดไดเพียงคลาสเดียว 10.3

วัฏจักรการทํางานของ Thread New start scheduler

wake up notify() I/O Completer

run() Running

Runnable

Block

Dead

sleep wait() block on I/O



New เปนสถานะเมื่อมีการสรางออบเจกตคลาสแบบ thread แตยังไมเริ่มทํางาน



Runnable เปนสถานะที่ออบเจกตแบบ thread พรอมที่จะทํางาน ซึ่งเกิดจากสาเหตุดังนี้

การเรียกใชเมธอด start() o การกลับมาจากสถานะ Block • Running เปนสถานะที่รันคําสั่งของออบเจกตแบบ thread เมื่อตัวจัดตารางเวลา จัดลําดับการทํางาน ของ thread โดยทํางานตามชุดคําสั่งในเมธอด run() • Block เปนสถานะที่เกิดจากเหตุการณดังนี้ o มีการเรียกใชเมธอด sleep() o มีการเรียกใชเมธอด wait() o ออบเจกตแบบเธรด รอรับการทํางานที่เปนอินพุตหรือเอาตพุต ออบเจกตแบบ thread ที่อยูในสถานะ Block จะกลับเขาสูสถานะ Runnable ไดอีกครั้งหนึ่งเมื่อมีเหตุ การดังนี้ o เมื่อหมดเวลาที่กําหนดในเมธอด sleep() o เมื่อมีออบเจกต อื่นมาเรียกเมธอด notify() หรือ notifyAll() ในกรณีที่ถูก Block ดวยเมธอด o

wait()

เมื่อมีการสงขอมูลที่เปนอินพุตหรือเอาตพุต ในกรณีที่ออบเจกตแบบเธรด รอรับการทํางานที่ เปนอินพุตหรือเอาตพุต Dead เปนสถานะสิ้นสุดการทํางานของ thread เนื่องจากสิ้นสุดการทํางานของเมธอด run() หรือเมื่อมี การสงออบเจกตประเภท Exception o



[email protected]

5/10

MultiThread

10.4

เมธอดของคลาส Thread •

public void run() เปนเมธอดที่ถูกเรียกใชเมื่อ thread อยูในสภาวะที่พรอมทํางาน



public void start() เปนเมธอดที่เรียกใชงานเพื่อกําหนดใหออบเจกตแบบ thread เริ่มทํางาน โดย

• •

• • • • •

10.5

Modern Programming Languages

เขาสูสถานะ Runnable public void stop() เปนเมธอดที่กําหนดใหออบเจกตแบบ thread หยุดการทํางาน ไมรอใหสิ้นสุด การทํางานเอง public void wait() ใหออบเจกตแบบ thread เขาสูสถานะ Block จนกวาจะถูก thread อื่นเรียก เมธอด notify() จึงจะกลับมาทํางานได แตการเรียกเมธอด wait() จะตองถูกเรียกในเมธอดที่ระบุ เปน synchronized เทานั้น public void notify() ใชสําหรับใหออบเจกตแบบ thread ที่กําลังทํางานอยู บอกให thread ที่อยู ในสถานะ Block รูวาสามารถเขามาทํางานตอได public String getName() เปนเมธอดที่ใชในการรับชื่อของ thread public static void sleep(long mills) throws InterruptedException เปนเมธอดที่กําหนดใหออบเจกตแบบ thread ที่อยูในสถานะ Running หยุดการทํางาน

คือเขาสู

สถานะ Block เปนเวลา mills มิลลิวินาที public static void yield() เปนเมธอดที่ทําใหออบเจกตแบบ thread ที่กําลังทํางานอยูออกจาก สถานะ Running ไปสูสถานะ Runnable เพื่อให thread เขามาทํางาน

Synchronization

กรณีที่ออบเจกตแบบเธรดใชขอมูลรวมกัน อาจเกิดปญหาที่เรียกวา Race Condition ขึ้นได ซึ่งเปนกรณีที่ ออบเจกตแบบเธรดตางแยงกันจัดการขอมูลทําใหไดขอมูลที่ผิดพลาด เราสามารถใชคียเวิรด synchronized เพื่อ ชวยล็อกชุดคําสั่งที่ออบเจกตแบบเธรดตองทํางานพรอมกันไวได UnSynchronized

Synchronized

count() count() count() count()

[email protected]

6/10

MultiThread

Modern Programming Languages

ตัวอยาง การใชคียเวิรด synchronized ในการล็อกชุดคําสั่งที่ออบเจกตแบบเธรดตองทํางานพรอมกันไว ได โดยโปรแกรมนี้ทําการนับตัวเลข

ผลที่ได



ในบรรทัดที่ 23 และ 24 ทําการสรางออบเจกตชนิด Thread และเรียกใชงานเมธอด start() นั่นคือ การสั่งใหเธรดเริ่มทํางานจากโปรแกรม หากไมพิจารณาเมธอด count() ซึ่งถูกระบุขางหนาดวยคีย เวิรด synchronized ผลลัพธที่ไดนาจะเกิดการทํางานออบเจกตชื่อ “A” และออบเจกตชื่อ “B” ทํางานไปพรอมกัน แตเนื่องจากเมธอด run() เรียกใชงานในเมธอด count() ซึ่งเมธอดนี้ถูกระบุ ดวยคียเวิรด synchronized ทําใหผลลัพธที่ไดเกิดการทํางานออบเจกตชื่อ “A” เสร็จกอน จึงเขา ไปทํางานออบเจกตชื่อ “B”

[email protected]

7/10

MultiThread

10.6

Modern Programming Languages

Deadlock

ในกรณีที่ออบเจกตแบบเธรดถูกเรียกใชงานเมธอด wait() โดยไมมี thread ใดเรียกเมธอด notify() ทํา ใหไมสามารถมีการทํางานใดๆเกิดขึ้นได จึงทําใหเกิดเหตุการณที่เรียกวา Deadlock

[email protected]

8/10

MultiThread

Modern Programming Languages

แบบฝกหัด 1.

สราง ThreadFinal.java public class ThreadFinal extends Thread { public ThreadFinal(String n) { super(n); } public void run() { for (int i=0;i<5;i++) { System.out.println(getName()); try { sleep(100); } catch( InterruptedException e ) { } } } public static void main(String args[]) { for (int i=0;i<20;i++) new ThreadFinal("Thread:"+String.valueOf(i)).start(); } } จากโปรแกรมขางบน เปลี่ยนใหเปนการใช implements อินเตอรเฟส Runnable ดังนี้ class ThreadFinal implements Runnable {

} public static void main(String args[]) { //จงทําใหโปรแกรมทํางานเหมือนกับโปรแกรมขางบน

} }

[email protected]

9/10

MultiThread 2.

Modern Programming Languages

สรางโปรแกรมนาฬิกา ใหตัวอยางโปรแกรมในการแสดงเวลา ดังนี้ สราง Clock.htm <APPLET CODE="Clock.class" WIDTH=400 HEIGHT=400>

สราง Clock.java import java.applet.Applet; import java.awt.*; import java.util.Date; public class Clock extends Applet { Date date; int hour,minute,second; Font f = new Font("MonoSpaced",Font.BOLD,64); public void init() { } public void paint( Graphics g ) { date = new Date(); int hour= date.getHours(); int minute= date.getMinutes(); int second= date.getSeconds(); String time = String.valueOf(hour)+":" +String.valueOf(minute)+":"+String.valueOf(second); g.setFont(f); g.setColor( Color.blue ); g.drawString( time, 50, 50 ); } }

จากตัวอยางโปรแกรมขางตน การแสดงผลเวลายังไมเปน real time คือเปนการแสดงผลเวลา ขณะรันโปรแกรม หรือมีการปรับ ขนาดหนาจอเทานั้น ใหนักศึกษาทําการแสดงผลเวลาแบบ real time พรอมทั้งเพิ่ม การแสดงผล วันเดือนป ดวย ***ใชการสรางออบเจกตแบบ thread ชวย

[email protected]

10/10

Related Documents

Chap10
November 2019 13
Chap10
December 2019 7
Chap10 Notes
October 2019 10
Solutions Chap10
November 2019 7
Chap10 Geiger
November 2019 10
066-071-chap10
October 2019 7