Threads

xiaoxiao2021-03-06  59

Threads

(Source: http://www.Artima.com)

Objects and java seminar by Bill Venners

Lecture handout

Agenda

Introduce multi-threading Show two ways to start a thread Talk about synchronization for mutual exclusion Discuss thread cooperation Look at the Java monitor Look at thread blocking, liveness, and scheduling

Multi-Threading in Java

Java Has Support for Multi-Threading Built Into The Language Threads Are "Sub-Processes" within a process

User-interface responsiveness Server responsiveness Can take advantage of multi-processors Each process has a private data segment Threads share the data segment of their process Two kinds of synchronization:.. Mutual exclusion and co-operation

Subclassing thread

In Java, threads are represented by an instance of class java.lang.Thread Two ways to define a thread starting point: extend Thread or implementing Runnable 1 // In file threads / ex1 / RepetitiveThread.java

2 public class reptitivethread extends thread {

3

4 Private Final String Msg;

5 private final long sleeptime;

6

7 Public RepetitiveThread (String Msg, Long SleepTime) {

8 this.msg = msg;

9 this.sleeptime = SleepTime;

10}

11

12 public void run () {

13

14 for (;;) {

15

16 System.out.println (MSG);

17 TRY {

18 SLEEP (SleepTime);

19}

20 catch (interruptedException e) {

twenty one }

twenty two }

twenty three }

twenty four }

1 // in File Threads / EX1 / EXAMPLE1.JAVA

2 public class example1 {

3

4 // arggs to this application specify "msg"

5 // and "sleeptime" for multiple triads.

6 // for Example, The Command:

7 //

8 / / $ JAVA EXAMPLE1 HI 100 LO 1000

9 // 10 // Requests Two Threads, ONE That Prints

11 // Out "Hi" Every 100 MilliseConds and

12 // Another That Prints Out "Lo" Every

13 // 1000 milliseconds.

14//

15 public static void main (string [] args) {

16

17 // Require an Even Argcount

18 int argcount = args.length;

19 IF ((argcount / 2) == 1) {

20 --Argcount;

twenty one }

twenty two

23 for (INT i = 0; i

twenty four

25 string msg = args [i];

26 long sleeptime = long.parselong (args [i 1]);

27

28 RepetitiveThread RT =

29 New RepetitiveThread (MSG, SleepTime);

30

31 rt.start ();

32}

33}

34}

Java Applications Keep Running Until The ARE NO More Non-daemon threads. Extending Thread Offen Difficult Because ITS HARD To FIT Thread Into The inheritance hierarchy.

Implementing Runnable

Flexible to Implement Runnable Than Extend Thread: 1 // In File Threads / EX2 / ANIMAL.JAVA

2 public class animal {

3}

1 // in File Threads / EX2 / CAT.JAVA

2 public class cat extends animal imports runnable {

3

4 Private Final String Msg;

5 private final long sleeptime;

6

7 Public Cat (String Msg, Long Sleeptime) {

8 this.msg = msg;

9 this.sleeptime = SleepTime;

10}

11

12 public void run () {

13

14 for (;;) {

15

16 System.out.println (MSG);

17 TRY {

18 thread.sleep (SleepTime);

19}

20 catch (interruptedException e) {

twenty one }

twenty two }

twenty three }

twenty four }

1 // in Source Packet in File Threads / EX2 / EXAMPLE2.JAVA2 Public Class Example2 {

3

4 // arggs to this application specify "msg"

5 // and "sleeptime" for multiple triads.

6 // for Example, The Command:

7 //

8 / / $ JAVA EXAMPLE1 Meow 100 Grrr 1000

9 //

10 // Requests Two Threads, One That Prints

11 // OUT "Meow" Every 100 MilliseConds and

12 // Another That Prints Out "GRRR" EVERY

13 // 1000 milliseconds.

14//

15 public static void main (string [] args) {

16

17 // Require an Even Argcount

18 int argcount = args.length;

19 IF ((argcount / 2) == 1) {

20 --Argcount;

twenty one }

twenty two

23 for (INT i = 0; i

twenty four

25 string msg = args [i];

26 long sleeptime = long.parselong (args [i 1]);

27

28 CAT Cat = New Cat (MSG, Sleeptime);

29

30 thread catthread = new thread (cat);

31 CATTHREAD.START ();

32}

33}

34}

MUTUAL EXCLUSION

Java has an object-oriented way to deal with thread synchronization. Data is protected by controlling access to code. (Hence, the data must be private.) Can mark blocks of code, or entire methods, as synchronized. Synchronized means only one thread AT A Time Can Execute The Code.

THREAD-SAFE OBJECT

A state machine RGBColor Object (not thread-safe) 1 // in file objectidioms / ex6 / rgbcolor.java

2 // Instances of this Class Are Not Thread-Safe.

3

4 public class rgbcolor {

5

6 private int R;

7 Private Int g;

8 Private Int B;

9

10 public RGBColor (int R, int G, int b) {

11

12 Checkrgbvals (R, G, B); 13

14 this.r = r;

15 THIS.G = g;

16 this.b = b;

17}

18

19 Public Void SetColor (int R, int G, int b) {

20

21 Checkrgbvals (R, G, B);

twenty two

23 this.r = r;

24 THIS.G = G;

25 this.b = b;

26}

27

28 / **

29 * Returns Color in An Array of Three INTS: R, G, AND B

30 * /

31 public int [] getColor () {

32

33 int [] retval = new int =

34 RetVal [0] = R;

35 RetVal [1] = g;

36 RetVal [2] = B;

37

38 return retval;

39}

40

41 public void invert () {

42

43 r = 255 - r;

44 g = 255 - g;

45 b = 255 - b;

46}

47

48 Private Static Void Checkrgbvals (int R, Int g, int b) {

49

50 IF (R <0 || R> 255 || G <0 || G> 255 ||

51 B <0 || B> 255) {

52

53 throw new illegalargumentException ();

54}

55}

56}

WRITE / WRITE CONFLICTS

ThreadStatementrgbColornoneobject represents green02550 GREEN blueblue thread invokes setColor (0, 0, 255) 02550 GREEN bluecheckRGBVals (0, 0, 255); 02550 GREEN bluethis.r = 0; 02550 GREEN bluethis.g = 0; 02550 GREEN blueblue gets preempted000 BLACK redred thread Invokes setColor (255, 0, 0) 000 Black redcheckrgbvals (255, 0, 0); 000 black redthis.r = 255; 000 black redthis.g = 0; 25500 red redThis.b = 0; 25500 red redred thread returns25500 red Bluelater, Blue Thread Continues25500 Red Bluethis.b = 25525500 Red Blueblue Thread Returns2550255 Magenta NoneObject Represents Magenta2550255 MAGENTA

Read / Write Conflicts

ThreadStatementrgbColornoneobject represents green02550 GREEN blueblue thread invokes setColor (0, 0, 255) 02550 GREEN bluecheckRGBVals (0, 0, 255); 02550 GREEN bluethis.r = 0; 02550 GREEN bluethis.g = 0; 02550 GREEN blueblue gets preempted000 BLACK redred thread INVOKES getColor () 000 black redint [] retval = new int [3]; 000 black redretval [0] = 0; 000 black redretval [1] = 0; 000 black redretval [2] = 0; 000 Black redreturn retval; 000 BLACK redred thread returns black000 BLACK bluelater, blue thread continues000 BLACK bluethis.b = 255000 BLACK blueblue thread returns00255 BLUE noneobject represents blue00255 BLUEThread-Safe RGBColor Object 1 // In file objectidioms / ex7 / RGBColor.java

2 // Instances of this class area thread-safe.

3

4 public class rgbcolor {

5

6 private int R;

7 Private Int g;

8 Private Int B;

9

10 public RGBColor (int R, int G, int b) {

11

12 Checkrgbvals (R, G, B);

13

14 this.r = r;

15 THIS.G = g;

16 this.b = b;

17}

18

19 Public Void SetColor (int R, int G, int b) {

20

21 Checkrgbvals (R, G, B);

twenty two

23 synchronized (this) {

twenty four

25 this.r = r;

26 THIS.G = G;

27 this.b = b;

28}

29}

30

31 / **

32 * Returns Color in an Array of Three INTS: R, G, AND B

33 * /

34 public int [] getColor () {

35

36 int [] retval = new int =

37

38 synchronized (this) {

39

40 RetVal [0] = R;

41 RetVal [1] = g;

42 RetVal [2] = B;

43}

44

45 return return;

46}

47

48 public synchronized void invert () {

49

50 r = 255 - r; 51 g = 255 - g;

52 b = 255 - b;

53}

54

55 Private Static Void Checkrgbvals (int R, int G, int b) {

56

57 if (r <0 || r> 255 || g <0 || g> 255 ||

58 B <0 || B> 255) {

59

60 throw new illegalargumentException ();

61}

62}

63}

Ready for Threads

ThreadStatementrgbColornoneobject represents green02550 GREEN blueblue thread invokes setColor (0, 0, 255) 02550 GREEN bluecheckRGBVals (0, 0, 255); 02550 GREEN blueblue thread acquires lock02550 GREEN bluethis.r = 0; 02550 GREEN bluethis.g = 0; 02550 GREEN blueblue gets preempted000 BLACK redred thread invokes setColor (255, 0, 0) 000 BLACK redcheckRGBVals (255, 0, 0); 000 BLACK redred thread blocks because object locked000 BLACK bluelater, blue thread continues000 BLACK bluethis.b = 255000 BLACK blueblue thread returns and releases lock00255 BLUE redlater, red thread acquires lock and continues00255 BLUE redthis.r = 255; 00255 BLUE redthis.g = 0; 2550255 MAGENTA redthis.b = 0; 2550255 MAGENTA redred thread returns and releases lock25500 RED noneobject represents red25500 RED

THREAD-SAFE OBJECT

Make instance variables private Figure out what the monitor regions should be and mark them synchronized Make objects thread-safe only if they'll actually be used in a multi-threaded environment Why? Performance hit from acquiring the lock and the possibility of deadlock

Synchronized Class Methods

Can Also Synchronize Class Methods, AS in: // in File Cat.java

PUBLIC Class Cat {

Public static final int max_lives = 9;

Private static cat [] lives = new cat [max_lives];

Public static synchronized cat [] getlives () {

Return Lives;

// ...

}

To Enter A Synchronized Class Method, Must Lock The Class's Java.lang.class Object.

Thread Cooperation

Mutual Exclusion IS Only Half of The Thread Synchronization Story: Java Also Supports Thread Cooperation. EXAMPLE: ProductER Thread and consumer thread

ThreadActionDataconsumerAny Data? NoneconsumerWAITnoneproducerBuffer Full? NoneproducerGive1, 2, 3producerNOTIFY1, 2, 3producerProcess1, 2, 3consumerAny Data? 1, 2, 3consumerTakenoneconsumerNOTIFYnoneconsumerProcessnoneconsumerAny Data? NoneconsumerWAITnoneproducerBuffer Full? NoneproducerGive5, 7, 11producerNOTIFY5, 7, 11producerProcess5, 7, 11producerBuffer Full? 5, 7, 11producerWAIT5, 7, 11consumerAny Data? 5, 7, 11consumerTakenoneconsumerNOTIFYnoneconsumerProcessnoneproducerBuffer Full? noneproducerGive13, 17, 19producerNOTIFY13, 17, 19producerProcess13, 17, 19consumerAny Data? 13, 17, 19consumerTakenoneconsumerNOTIFYnoneconsumerProcessnoneconsumerAny Data? noneconsumerWAITnone

The Java Monitor

A Monitor Is Like a Building That Contains One Special Room (Which Usually Contains Some Data) That Can Be Occupied by Only One Thread At A Time.

Cooperation Example 1 // in File Threads / EX6 / INTBUFFER.JAVA

2 public class int buffer {

3

4 private final int buffsize;

5 private int [] buff;

6

7 // Keeps Track of Next Buff Array Location

8 // TO BE FILED. WHEN NEXTBUFFINDEX ==

9 // Buffsize, The Buffer Is Full. By

10 // NextBuffIndex == 0, The Buffer IS

11 // Empty.

12 private int nextbuffindex;

13

14 INTBUFFER (int buffsize) {

15

16 this.buffsize = buffsize;

17 buff = new int [buffsize];

18}

19

20 Public Synchronized Void Add (INT VAL) {

twenty one

22 While (NextBuffIndex == Buffsize) {23

24 try {

25 Wait ();

26}

27 Catch (InterruptedException E) {

28}

29}

30

31 buff [nextbuffindex] = VAL;

32 NextBuffIndex;

33

34 NotifyAll ();

35}

36

37 public synchronized int removenext () {

38

39 While (NextBuffIndex == 0) {

40

41 TRY {

42 Wait ();

43}

44 Catch (InterruptedException E) {

45}

46}

47

48 // this Buffer IS FIFO, SO Remove The

49 // First Int Added and Shift The Rest

50 // Over.

51 int val = buff [0];

52

53 - NextBuffIndex;

54 for (int i = 0; i

55

56 BUFF [I] = BUFF [i 1];

57}

58

59 NotifyAll ();

60 return val;

61}

62}

1 // in File Threads / EX6 / primenumbergenerator.java

2 public class primenumbernerator imports runnable {

3

4 Private Final IntBuffer BUFF;

5

6 public primeNumbergenerator (intbuffer buff) {

Seduce

8 this.buff = buff;

9 }

10

11 public void run () {

12

13 int priMenum = 1;

14 int NumToCheck = 2;

15

16 buff.add (primes);

In one

18 for (;;) {

19

20 Boolean Foundprime = TRUE;

twenty one

22 for (int Divisor = NumToCheck / 2; Divisor> 1;

23 - Divisor) {

twenty four

25 IF (NumToCheck% Divisor == 0) {

26 FoundPrime = false;

27 Break;

28}

29}

30

31 IF (FoundPrime) {

32 primenum = Numtocheck;

33 Buff.Add (Primenum);

34}

35

36 NumToCheck;

37}

38}

39}

1 // in Source Packet in File Threads / EX6 / INTPRINTER.JAVA

2 public class intprinter imports runnable {

3

4 Private Final IntBuffer BUFF;

5

6 public intprinter (intBuffer buff) {

Seduce

8 this.buff = buff;

9 }

10

11 public void run () {

12

13 for (;;) {

14

15 int val = buff.removenext ();

16 System.out.println (VAL);

17}

18}

19}

1 // in File Threads / EX6 / EXAMPLE6.JAVA

2 public class example6 {

3

4 public static void main (string [] args) {

5

6 INTBUFFER BUFF = New IntBuffer (3);

Seduce

8 primenumbergenerator png = new primeNumbergenerator (buff);

9 INTPRINTER IP = New INTPRINTER (BUFF);

10

11 thread product = new thread (png);

12 Thread Consumer = New Thread (IP);

13

14 product ();

15 consumer.start ();

16}

17}

Thread blocking

A Thread Can Be in Any of 4 States:

New Runnable Dead Blocked A Thread Can Be Blocked for Any of 4 Reasons:

Sleeping (The Thread Invoked Sleep ()) in Entry Set of A Monitor (The Thread Invoked Wait () WAITING for An I / O Operation

Program Liveness

Liveness Means a Program Will Isn't "Hung" And Will Eventually Do Something Useful. A Multi-Threaded Program CAN Lose ITS Liveness In Several Ways:

DEADLOCK UNSATISFied Wait Condition Starvation Thread Safety OFTEN Conflicts with Thread Liveness.

If no synchronized methods, program can't deadlock.thread scheduling

THE JVM HOLDS NON-BLOCKED Threads in priority-based scheduling queues.

By Default, Each New Thread Gets The Same Priority As ITS Creator. Can Change A Thread's Priority by Invoking SetPriority (). JVMS Are Encouraged TO:

Cycle through highest priority threads (not necessarily in a fair way). Preempt lower priority threads in favor of higher priority threads. Invoking yield () indicates to the JVM that you are ready for a rest. Do not depend on "time-slicing For Program Correctness.

Exercise: The Dreaded, Threaded Fibonacci Generator Create a Java application named Problem1 that generates the Fibonacci sequence The first two numbers of the Fibonacci sequence are 1 and 1. Each subsequent number is calculated by summing the previous two numbers, as in:. 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, and so on. Input to the Application The Problem1 application will write the Fibonacci sequence to the standard output. The Problem1 application, which requires no command line arguments, Should Print Out The First 92 Fibonacci Numbers The Output Will Look Like: 1

1

2

3

5

8

13

<...>

The maximum of 92 arises because the 93rd Fibonacci number is too big to express in a Java long. The biggest Fibonacci number that will fit in Java's long (a 64 bit signed integer) is 7540113804746346429L, which is the 92nd Fibonacci number. Structure of the Application The Application Will Be Made Up of Four Classes, Named: FibonacciGenerator.java

Longbuffer.java

LongbufferToOutputthread.java

Problem1.java

The application will contain three threads, the main thread and two extra threads that the main thread will start. The two extra threads are defined by FibonacciGenerator, which implements Runnable, and LongBufferToOutputThread, which directly subclasses class Thread. The main () method of the Problem1 application will create and start these two threads and connect the output of the FibonacciGenerator thread to the input of the LongBufferToOutputThread. The Fibonacci numbers will be generated by the FibonacciGenerator thread, which writes one long value at time into a LongBuffer. The LongBufferToOutputThread will then read long's from the LongBuffer and write them to the standard output Classes of the Application Class Problem1 The main () method should:... Create a LongBuffer object with a buffer size of 3. Create a FibonacciGenerator object Create a LongBufferToOutputThread object Start the FibonacciGenerator And longbuffertooutputthread threads. this main thread is now finished and can just return from the main () method Class LongBuffer You can base this class on the IntBuffer class from the lecture slides, which is in the Threads / examples / ex6 directory of the sample code:. // In source packet in file threads / ex6 /Intbuffer.java

Public class int buffer {

PRIVATE FINAL INT BUFFSIZE

PRIVATE INT [] BUFF;

// Keeps Track of Next Buff Array Location

// to be filled. when nextbuffindex ==

// Buffsize, The Buffer Is Full. by

// nextbuffindex == 0, The Buffer IS

// Empty.

Private int nextBuffIndex;

INTBUFFER (int buffsize) {

THIS.BUFFSIZE = BUFFSIZE;

BUFF = New Int [buffsize];

}

Public synchronized void add (int val) {

While (NextBuffIndex == buffsize) {

Try {

Wait ();

}

Catch (InterruptedExcect E) {}

}

BUFF [NextBuff "= VAL;

nextBuffIndex;

NotifyAll ();

}

Public synchronized int transnext () {

While (NextBuffIndex == 0) {

Try {

Wait ();

}

Catch (InterruptedException E) {

}

}

// this buffer is FIFO, SO Remove the

// first int added and shift the rest

// over.

INT VAL = BUFF [0];

--NextBuffIndex;

For (int i = 0; i

BUFF [I] = BUFF [i 1];

}

NotifyAll ();

Return Val;

}

}

Basically, LongBuffer has to do a similar thing to what IntBuffer does, but for longs instead of ints. It needs an add () method and a long removeNext () method, and it must assume different threads will be calling these methods. Thus, the add () and removeNext () methods must be synchronized and use wait () and notifyAll () class FibonacciGenerator This class extends Object and implements Runnable It has one constructor, which takes one argument:... a LongBuffer reference It's run () method simply produces the Fibonacci sequence one long at a time and writes each one to the LongBuffer as it is produced. to indicate that it is finished producing numbers, the FibonacciGenerator class declares a public static final int END_OF_DATA field that is initialized to -1. When the FibonacciGenerator's run () method is done generating the first 92 Fibonacci numbers, it writes an END_OF_DATA to the LongBuffer. After that, this thread is finished and the run () method simply returns. Class LongBufferToOutput . Thread This class extends Thread It has one constructor, which takes one argument:. A LongBuffer It's run () method simply reads one long at a time from the LongBuffer and writes it as a String to the standard output, placing a return ( ' / n '

转载请注明原文地址:https://www.9cbs.com/read-84287.html

New Post(0)