Chapter13

  • 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 Chapter13 as PDF for free.

More details

  • Words: 2,018
  • Pages: 12
CS313: Object-Oriented Programming

บทที่ 13: Multithreading

บทที่ 13 Multithreading 13.1 Introduction ในการทํางานของโปรแกรมโดยทั่วไป จะเปนการทํางานตามลําดับของคําสั่งทีละคําสั่ง (sequential processing) แตจะมีการทํางานแบบหนึ่งซึ่งงานตางๆ สามารถทําไดพรอมกัน โดยไมตองรอใหงานนั้นๆ เสร็จ เชน ระบบการหายใจของมนุษย สามารถทํางานพรอมกับระบบการยอยอาหาร หรือสัมผัสทั้ง 5 ของมนุษย อัน ไดแก การมองเห็น การฟง การไดกลิ่น การลิ้มรส และการสัมผัส ในทางคอมพิวเตอรก็มีระบบการทํางานใน ลักษณะนี้เชนกัน ตัวอยางเชน เราสามารถ compile โปรแกรม พรอมกับการสั่งพิมพเอกสาร หรือการเปดเพลง mp3 การทํางานที่พรอมกันหลายๆ งานในเวลาหนึ่งๆ เรียกวา parallel processing หรือ concurrency processing ภาษา Java เปนภาษาที่รองรับการทํางานทั้งแบบ sequential และ แบบ concurrency โดยที่การ เขียนโปรแกรมแบบ concurrency นัน้ จะอยูในลักษณะของ thread thread เปนกระบวนการเขียนโปรแกรมที่สามารถทําใหเกิดงานไดหลายงานในหนึ่งโปรแกรม การ เขียนโปรแกรมแบบ thread ในภาษา Java นี้จะเปน multithreading ซึง่ คุณสมบัตินี้ไมมีในภาษาอื่น เชน C หรือ C++ ซึง่ ถูกจัดเปนภาษาประเภท single-threaded language 13.2 Thread Creating ในการสราง thread สามารถทําได 2 วิธีคือ โดยการสืบทอดจาก class Thread และอีกวิธีหนึ่งคือ การ implement interface ชื่อ Runnable ตัวอยางที่ 1 การสราง thread โดยการสืบทอดจาก class Thread // Creates three threads that run concurrently. public class Simultaneous public static Soda one = Soda two = Soda three

} }

2/2545

{

void main (String[] args) new Soda ("Coke"); new Soda ("Pepsi"); = new Soda ("Mirinda");

{

one.start(); // The start method begins thread processing two.start(); three.start(); // method main

// class Simultaneous

1

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 1 (ตอ) // A thread that prints a message 100 times. class Soda extends Thread

{

private String name; Soda (String str) { name = str; } // constructor Soda // The run method defines the concurrent code. public void run() { for (int count = 0; count < 100; count++) System.out.println (name); } // method run }

// class Soda

ตัวอยางที่ 1 เปนตัวอยางการสราง class ชื่อ Soda ซึง่ เปน sub-class ของ class Thread ใน class Thread จะมี method ทีช่ ื่อวา run() ซึง่ จะตองถูก override โดย sub-class ภายใน method run() จะบรรจุ code ทีต่ อ งการใหทํางานเมื่อมีการสั่งให thread นัน้ ๆ ทํางาน โดย method start() ใน class Simultaneous มีการสราง 3 object ชื่อ one, two และ three จาก class Soda ดังนั้นทั้ง 3 object ก็คือ thread นั่นเอง โดย object ทัง้ 3 จะถูกทํางานจากคําสั่ง one.start(); two.start(); และ three.start() ตามลําดับ ในการทํางานจะพบวา ขอความที่ถูกพิมพ จะปะปนกันไป ไมเรียงตามลําดับของการ สัง่ งาน ทั้งนี้เนื่องจากแตละ thread มีอสิ ระในการประมวลผล ตัวอยางที่ 2 การสราง thread โดยการ implement interface ชือ่ Runnable import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class DigitalThreads extends java.applet.Applet implements Runnable { Font theFont = new Font ("TimesRoman", Font.BOLD, 24); Date theDate; Thread runner; public void start() { if (runner == null) { runner = new Thread(this); runner.start(); } } // method start public void stop() { if (runner != null) { runner.stop(); runner = null; } } // method stop

2/2545

2

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 2 (ตอ) public void run() { while (true) { theDate = new Date(); repaint(); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } // method run public void paint (Graphics g) { g.setFont (theFont); g.drawString (theDate.toString(), 10, 50); } // method paint } // class DigitalThreads

<TITLE>DigitalThreads Applet <APPLET CODE="DigitalThreads.class" WIDTH=430 HEIGHT=100>

ตัวอยางที่ 2 เปน applet ทีแ่ สดงเวลาปจจุบันของเครื่องคอมพิวเตอร โดยจะมีการสราง object ชื่อ runner จาก class Thread method ทีใ่ ชมีทั้งหมด 4 method ดังนี้ 1. start() เปน method ทีจ่ ะถูกเรียกเมื่อมีการเริ่มประมวลผล applet DigitalThreads 2. stop() เปน method ทีจ่ ะถูกเรียกเมื่อ applet นีจ้ บการทํางาน 3. run() เปน method ทีจ่ ะทํางานเมื่อ thread ที่ชื่อ runner ถูกเรียกโดยคําสั่ง runner.start() 4. paint() เปน method ทีใ่ ชในการแสดงผลทาง graphics 13.3 Thread States: Life Cycle of a Thread วงจรชีวิตของแตละ thread เริ่มตนที่ขั้น born เมือ่ ถูกเริ่มสราง และจะอยูที่ขั้นนี้จนกระทั่ง method start ถูกเรียกประมวลผล ซึ่งจะทําให thread นั้นๆ อยูที่ขั้น ready โดยที่ thread ที่มี priority สูงที่สุดจะถูก ทํางานกอนโดยเขาสูขั้น running แตละ thread จะเขาสูขั้นสุดทายของวงจรชีวิตคือ dead เมื่อ thread นั้น ทํางานใน method run เสร็จเรียบรอย หรือเมื่อถูก terminate ดวยเหตุผลใดๆ ก็ตาม

2/2545

3

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ในชวงที่ thread หนึ่งๆ อยูในขั้น running thread นัน้ จะสามารถยายไปอยูในขั้น blocked ได เมื่อ มีการเรียกใชงาน input หรือ output ในกรณีนี้ thread ดังกลาวจะกลับมาสูขั้น running เมือ่ กระบวนการ input หรือ output ไดทํางานเสร็จสิ้นลง เมือ่ มีการเรียก method sleep() ใน thread ทีอ่ ยูในขั้น running จะสงผลให thread ดังกลาวเขาสู ขั้น sleeping ซึง่ เหมือนกับการหยุดการทํางานชั่วคราว โดยทั่วไปจะมีการกําหนดเวลาสําหรับการอยูในขั้น sleeping ซึง่ เมือ่ หมดเวลาที่กําหนดไวแลว thread นัน้ ๆ จะกลับสูขั้น running อีกครั้งหนึ่ง เมื่อ thread ในขั้น running มีการเรียก method wait() จะสงผลให thread ดังกลาวเปลี่ยนสถานะ มาอยูในขั้น waiting เพือ่ ทําการรอการตอบสนองจาก object ทีร่ ะบุไวเมื่อมีการเรียก method wait() thread ในขั้น waiting จะกลับเขาสูขั้น running เมือ่ มีการเรียก method notify() หรือ notifyAll() โดย thread อื่นที่เกี่ยว ของกับ object นั้นๆ วงจรชีวิตของ Thread สามารถสรุปไดดังภาพตอไปนี้

born start() I/O completion

sleep interval expires

ready

notify() notifyAll()

Quantum expiration yield interrupt

dispatch (assign a processor)

running issue I/O

wait()

waiting

2/2545

sleep() sleeping

complete

dead

blocked

4

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

13.4 Thread Synchronization ปญหาทีอ่ าจเกิดขึ้นเมื่อมีการทํางานหลาย thread พรอมๆ กัน โดยที่แตละ thread มีการใชขอมูล รวมกัน อาจเกิดขอผิดพลาดกับขอมูลดังกลาวได วิธกี ารแกปญหานี้คือ การใช method synchronized โดยที่ method นีจ้ ะอนุญาตใหเพียง 1 thread เทานั้นที่จะ execute คําสั่งตางๆ ภายใน method synchronized ได สวน thread อืน่ ๆ จะตองรอ (wait) จน กวา thread นัน้ ทํางานใน method synchronized เสร็จกอน ตัวอยางที่ 3 Producer / consumer relationship without Thread Synchronization // Show multiple threads modifying shared object. public class SharedCell { public static void main( String args[] ) { HoldIntegerUnsynchronized h = new HoldIntegerUnsynchronized(); ProduceInteger p = new ProduceInteger( h ); ConsumeInteger c = new ConsumeInteger( h ); p.start(); c.start(); } }

// Definition of threaded class ProduceInteger public class ProduceInteger extends Thread { private HoldIntegerUnsynchronized pHold; public ProduceInteger( HoldIntegerUnsynchronized h ) { super( "ProduceInteger" ); pHold = h; } public void run() { for ( int count = 1; count <= 10; count++ ) { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); } pHold.setSharedInt( count ); }

2/2545

5

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 3 (ตอ) System.err.println( getName() + " finished producing values" + "\nTerminating " + getName() ); } } // Definition of threaded class ConsumeInteger public class ConsumeInteger extends Thread { private HoldIntegerUnsynchronized cHold; public ConsumeInteger( HoldIntegerUnsynchronized h ) { super( "ConsumeInteger" ); cHold = h; } public void run() { int val, sum = 0; do { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); } val = cHold.getSharedInt(); sum += val; } while ( val != 10 ); System.err.println( getName() + " retrieved values totaling: " + sum + "\nTerminating " + getName() ); } }

// Definition of class HoldIntegerUnsynchronized public class HoldIntegerUnsynchronized { private int sharedInt = -1; public void setSharedInt( int val ) { System.err.println( Thread.currentThread().getName() + " setting sharedInt to " + val ); sharedInt = val; } public int getSharedInt() { System.err.println( Thread.currentThread().getName() + " retrieving sharedInt value " + sharedInt ); return sharedInt; } }

2/2545

6

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

สังเกตุผลลัพธที่ไดหลังจาก run class SharedCell ตัวอยางที่ 4 Producer / consumer relationship with Thread Synchronization // Show multiple threads modifying shared object. public class SharedCell { public static void main( String args[] ) { HoldIntegerSynchronized h = new HoldIntegerSynchronized(); ProduceInteger p = new ProduceInteger( h ); ConsumeInteger c = new ConsumeInteger( h ); p.start(); c.start(); } }

// Definition of threaded class ProduceInteger public class ProduceInteger extends Thread { private HoldIntegerSynchronized pHold; public ProduceInteger( HoldIntegerSynchronized h ) { super( "ProduceInteger" ); pHold = h; } public void run() { for ( int count = 1; count <= 10; count++ ) { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); } pHold.setSharedInt( count ); } System.err.println( getName() + " finished producing values" + "\nTerminating " + getName() ); } }

2/2545

7

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 4 (ตอ) // Definition of threaded class ConsumeInteger public class ConsumeInteger extends Thread { private HoldIntegerSynchronized cHold; public ConsumeInteger( HoldIntegerSynchronized h ) { super( "ConsumeInteger" ); cHold = h; } public void run() { int val, sum = 0; do { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); } val = cHold.getSharedInt(); sum += val; } while ( val != 10 ); System.err.println( getName() + " retrieved values totaling: " + sum + "\nTerminating " + getName() ); } }

// Definition of class HoldIntegerSynchronized that // uses thread synchronization to ensure that both // threads access sharedInt at the proper times. public class HoldIntegerSynchronized { private int sharedInt = -1; private boolean writeable = true; // condition variable public synchronized void setSharedInt( int val ) { while ( !writeable ) { // not the producer's turn try { wait(); } catch ( InterruptedException e ) { e.printStackTrace(); } } System.err.println( Thread.currentThread().getName() + " setting sharedInt to " + val ); sharedInt = val; writeable = false;

2/2545

8

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 4 (ตอ) notify(); // tell a waiting thread to become ready } public synchronized int getSharedInt() { while ( writeable ) { // not the consumer's turn try { wait(); } catch ( InterruptedException e ) { e.printStackTrace(); } } writeable = true; notify(); // tell a waiting thread to become ready System.err.println( Thread.currentThread().getName() + " retrieving sharedInt value " + sharedInt ); return sharedInt; } }

เปรียบเทียบผลลัพธที่ไดกับตัวอยางที่ 3 13.5 Controlling Threads จากวงจรชีวิตของ thread ทําใหทราบวา thread ตางๆ สามารถถูกควบคุมไดโดย method ตางๆ ดังนี้ ! suspend() เปนการหยุดการทํางานของ thread ชัว่ คราว ! resume() เปนการเรียก thread ที่ถูก suspend ขึน้ มาทํางานใหม ! sleep ( long milliseconds) เปนการหยุดการทํางานของ thread นานตามเวลาที่กําหนด ตัวอยางที่ 5 bouncing ball import java.awt.event.*; import java.applet.Applet; import java.awt.*; // Simulates a ball on a rubber band. public class Bouncing_Ball extends Applet { private final int SIZE= 300; private Ball ball = new Ball(150, 10, 250, 200); private Graphics page;

2/2545

9

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 5 (ตอ) private Control_Panel controls; public void init() { setVisible (true); setSize (SIZE, SIZE); page = getGraphics(); page.setXORMode (getBackground()); } // method init public void start() { controls = new Control_Panel (Thread.currentThread()); controls.start(); ball.pause(); while (ball.moving()) { ball.bounce (page); } } // method start } // class Bouncing_Ball // Various buttons that suspend and resume execution of the applet thread. class Control_Panel extends Thread { private Button suspend = new Button ("suspend"); private Button resume = new Button ("resume"); private Frame frame = new Frame ("Bouncing Ball Control Panel"); private Thread applet_thread; Control_Panel (Thread applet_thread) { this.applet_thread = applet_thread; } // constructor Control_Panel public void run() { Resume_Action resume_action = new Resume_Action (applet_thread); Suspend_Action suspend_action = new Suspend_Action (applet_thread); suspend.addActionListener (suspend_action); resume.addActionListener (resume_action); frame.setLayout (new FlowLayout()); frame.add (suspend); frame.add (resume); frame.pack(); frame.setLocation (250, 200); frame.setVisible (true); } // method run } // class Control_Panel // Action for the suspend button class Suspend_Action implements ActionListener { Thread applet_thread; Suspend_Action (Thread applet_thread) { this.applet_thread = applet_thread; } // Constructor Suspend_Action public void actionPerformed (ActionEvent action) { applet_thread.suspend(); // Suspends the animation } // method actionPerformed } // class Suspend_Action

2/2545

10

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 5 (ตอ) // Action for the suspend button class Resume_Action implements ActionListener { Thread applet_thread; Resume_Action (Thread applet_thread) { this.applet_thread = applet_thread; } // constructor Resume_Action public void actionPerformed (ActionEvent action) { applet_thread.resume(); // Resumes the animation } // method actionPerformed } // class Resume_Action // Draws the ball and simulates its movement. class Ball { private final int MOVE = 2; private final float DISTANCE = 0.97f; private final int SIZE = 20; private final int PAUSE = 5; private int x; private int start_y; private int end_y; private int length; private boolean moving_up = true; Ball (int new_x, int new_start_y, int new_end_y, int new_length) { x = new_x; start_y = new_start_y; end_y = new_end_y; length = new_length; } // constructor Ball public void pause() { try { Thread.currentThread().sleep (PAUSE); // Pauses the animation for a short time } catch (InterruptedException exception) { System.out.println ("have an exception"); // ignore the exception and continue } } // method pause void move() { if (moving_up) { end_y = end_y - MOVE; } else { end_y = end_y + MOVE; } } // method move

2/2545

11

CS313: Object-Oriented Programming

บทที่ 13: Multithreading

ตัวอยางที่ 5 (ตอ) void draw_ball (Graphics page) { page.drawOval (x-(SIZE/2), end_y, SIZE, SIZE); page.drawLine (x, start_y, x, end_y); } // draw_ball public boolean moving() { return length != 0; } // method moving public void bounce (Graphics page) { for (int count = 1; count < length; count += MOVE) { draw_ball (page); pause(); draw_ball (page); move(); } moving_up = !moving_up; length = (int) (DISTANCE * length); } // method bounce } // class Ball

<TITLE>Bouncing Ball Applet <APPLET CODE="Bouncing_Ball.class" WIDTH=300 HEIGHT=300>

2/2545

12

Related Documents

Chapter13
May 2020 5
Chapter13
November 2019 12
Chapter13-1.docx
November 2019 13
Gita Tamil Chapter13
June 2020 3