Two multithreaded implementations of Java

First, two ways to create multithreading

In Java, there are two ways to create multiple threads:

1, by inheriting the Thread class, overriding the Thread’s run () method, placing the thread running logic in it

2, through the implementation of the Runnable interface, Thread class
instantiation, in practical applications, we often use multi-threaded, such as station ticketing system, the station’s ticket outlets, equivalent to each thread. When we do this system, we might think of two ways to implement, inherit the Thread class, or implement the Runnable interface. Now look at the two results achieved in these two ways.

Program 1:

Package Z; class MyThread extendsThread{privateintticket = 10; privateString name; publicMyThread (String name) {this.name =name;} {for (publicvoidrun) (inti = 0; I 500; < i++) {if (this.ticket > 0 System.*out*.Println (this.name+) {"----> ticket;" + (this.ticket--));}}}} {public classThreadDemo publicstaticvoidmain (String[] args) {MyThread mt1= newMyThread ("window"); MyThread mt2= newMyThread ("two window"); MyThread mt3= newMyThread ("three window"); (mt1.start); mt2.start (mt3.start); ();}}

Operation result:

A window on the ticket window ticket number ----> 10 ----> 9, the ticket window, ticket window ----> 8 ----> 7, the ticket window, ticket window ----> 6 ----> 5, the ticket window, ticket window ----> 4 ----> 3, the ticket window - > window; 2, the ticket window No. three ticket ----> 1 ----> 10 ----> window No. three ticket window ticket number three; 9 ----> three ----> 8 window ticket window ticket number two; 7 ----> 10 ----> window No. two ticket window ticket number two; 9 ----> three ----> 8 window ticket window; 6 No. three ticket window ticket number three ----> 5 ----> three ----> 4 window ticket window ticket number two; 3 ----> 7 ----> window No. two ticket window ticket number two; 6 ----> two ----> 5 window ticket window ticket number two - 4; -> windows 3 No. two ticket window ticket number two ----> 2 ----> 1 ----> three window ticket window ticket number three; 2 ----> 1

Program 2:

Package Z; class MyThread1 implementsRunnable{privateintticket =10; publicvoidrun (for) {(inti = 0; i< 500; i++) {if (this.ticket> 0) {System.*out*.println (Thread.*currentThread*) (.GetName) ("----> + + ticket;" (this.ticket--));}}}} {publicstaticvoidmain (String[] args public classRunnableDemo three) {/ / mt = (newMyThread1) MyThread1 thread; Thread T1 = newThread (MT, "a window"); Thread T2 = newThread (MT, "two window"); Thread T3 = newThread (MT, "three window"); (t1.start); T2.start (); t3.start ();}

Operation result:

No. three window ticket window ticket number three ----> 10 ----> three ----> 7 window ticket window ticket number three; 6 ----> 5 ----> window No. three ticket window ticket number three; 4 ----> 3, the ticket window ticket window No. two 8 ----> ----> 9, the ticket window - 1 > No. three ticket window ----> 2

Why are the results of the two programs different?

First procedures, the equivalent of three out of three things: 10 tickets to three separate tasks window, they all do all the things to sell tickets each to complete all the tasks, because MyThread inherits the Thread class, so when the new
MyThread to create the three objects at the same time to create three a thread.

Second procedures, quite out of a ticket 10 tasks to three people go together to complete the new
MyThread is equivalent to create a task, then instantiate three Thread, creating three threads that arrange three windows to perform.

The graph shows the following:

Two multithreaded implementations of Java
multithreaded.Jpg

Through the above analysis, we find that there are two big differences between the two threads:

(1)
Thread is inheritance; Runnable is the way to implement interfaces.

(2)
Thread means that multiple threads perform their own tasks, namely, data independence; Runnable means that multiple threads perform a task together, that is, data sharing.


In most cases, you should use the Runnable interface if you want to override the run () method without overriding the other Thread methods. This is important because unless the programmer intends to modify or enhance the basic behavior of the class, subclasses should not be created for the class (Thread).

Two, hidden problems

In the second method, the 3 Thread objects together to perform a Runnable object code, this may cause the thread unsafe, for example, may ticket will output -1 (if we add System.out… Statement. The thread sleep operation, will likely).

This is because a thread in the judgment of ticket 1> 0, yet by 1, another thread will have ticket by 1, to 0, then the next thread before the ticket has been reduced by 1, -1.

This involves adding synchronization operations (i.e., mutex) to ensure that only one thread at the same time performs the operations in each for loop.

In the first approach, synchronization operations are not required because each thread executes the code in its own Thread object, and there is no case where multiple threads execute the same method together.

Program 1:

Package Z; class MyThread1 implementsRunnable{(privateintticket = 10; publicvoidrun) {for (inti = 0; i< 500; i++) {if (this.ticket> 0) {try{Thread.*sleep* (100); System.*out*.println (Thread.*currentThread*) (.GetName) ("----> + + ticket;" (this.ticket--);}catch (Exception E) (e.printStackTrace) {}}}}}); public classRunnableDemo publicstaticvoidmain (String[] args) {{/ / three = newMyThread1 (MT) MyThread1 thread; Thread T1 = newThread (MT, "a window"); Thread T2 = newThread (MT, "two window"); Thread T3 = newThread (MT, "three window"); (t1.start); t2.start (t3.start); ();}}

Operation result:

A window on the ticket window ticket number two ----> 10 ----> three ----> 10 window ticket window ticket number; 9 ----> three ----> 8 window ticket window ticket number two; 7 ----> 8, the ticket window ticket window No. three 6 ----> ----> 4; window No. two ticket window of 5 ----> No. three ticket window ticket number two ----> 3 ----> 2, the ticket window ticket window No. two 3 ----> 1 ----> three ----> -1 window ticket window ticket number; ----> 0

Program 2:

Package Z; class MyThread1 implementsRunnable{(privateintticket = 1000; publicvoidrun) {for (inti = 0; i< 5000; i++) {synchronized (this) {if (this.ticket> 0) {System.*out*.println (Thread.*currentThread*) (.GetName) ("----> + + ticket;" (this.ticket--));}}}}} public classRunnableDemo publicstaticvoidmain (String[] args) {{/ / three = newMyThread1 (MT) MyThread1 thread; Thread T1 = newThread (MT, "a window"); Thread T2 = newThread (MT, "two window"); Thread T3 = newThread (MT, window three); t1.start (); t2.start (); t3.start ();}

Operation result:

A window on the ticket window ticket number ----> 10 ----> 9, the ticket window, ticket window ----> 8 ----> 7, the ticket window, ticket window ----> 6 ----> 5, the ticket window, ticket window ----> 4 ----> 3, the ticket window - > window; 2 a ticket No. ----> 1

Note that all 10 tickets here are sold at window No. 1. This is because the synchronized is used and the votes are too small, and the 10 tickets have been sold out at the time the T1 locks the this object. When T2 or T3 is locked, the this object is sold without a ticket. If the vote is a little more, for example, there are tens of thousands of pieces, you can see the three window in the ticket.