Get excellent performance (i) - introducing threads, threads and Runnable Jeff Friesen
Query active thread
In some cases, you may want to know which threads in your program are activated. Thread supports a pair method to help you complete this task: activeCount () and enumerate (thread [] thdarray). But those methods are only working in the thread group of the current thread. In other words, those methods only identify the active thread of the same thread group belonging to the current thread. (I will discuss threading groups in the next series of articles.)
Static ActiveCount () method Returns the number of threads that are active in the thread group in the current thread. A program utilizes the integer return value of this method to set the size of a THREAD reference array. Retrieve those references, the program must call the static ENUMERATE (THREAD [] THDARRAY method. The integer return value of this method determines the total number of Enumerate (Thread [] Thdarray) in the Thread reference stored in the array. To see how these methods work together, please see Table 6:
Table 6. Census.java
// census.java
Class CenSUS
{
Public static void main (string [] args)
{
Thread [] threads = new thread [threeRead.activecount ()];
INT n = thread.enumerate (threads);
For (int i = 0; i System.out.println (threads [i] .tostring ()); } } At runtime, this program will produce the following output: Thread [main, 5, main] The output is displayed, and the start thread is running. The on the left main represents the name of the thread. 5 Display the priority of the thread, the main MAIN represents the thread group. You may be very disappointed that you can't see any system threads, such as garbage collector threads in the output. That limit is generated by thread's enumerate (thread [] thdarray) method, which only asks the active thread of the current thread thread group. However, the ThreadGroup class contains a variety of enumerate () methods allow you to capture references to all active threads without the threaded group. In the series of series, I will show you how to list all references when I discussed ThreadGroup. caveat When you reiterate an array, do not rely on the return value of ActiveCount (). If you do this, your program will throw a risk of NullPointerexception objects. why? Between call activecount () and enumerate (Thread [] Thdarray), one or more threads may end. As a result, enumerate (thread [] thdaRray) can copy a few thread reference into an array. Therefore, only consider the return value of the ActiveCount () as the maximum value of the array. Similarly, consider the return value of Enumerate (Thread [] ThdArray as the number of active threads when the method is called in one program. Antisocar If your program fails and you suspect that the problem is in the thread, you can learn more details of the thread by calling Thread Dumpstack () and TSTRING (). The static dumpstack () method provides a new Exception ("stack trace"). PrintStackTrace () package, print a stack that tracks the current thread. TSTRING () Returns a string of the name, priority, and thread group of threads based on the following format: thread [thread-name, priority, thread-group]. (you will learn more about priority in the series Knowledge of rights.) Tips In some places, this article refers to the concept of current threads. If you need to access the Thread object that describes the current thread, call the Static CurrentThread () method of THREAD. Example: thread current = thread.currentthread (). Level system Not all threads are created equally. They are divided into two categories: users and supervision. A user thread performs a very important job for program users, and the work must be completed before the program ends. Instead, a supervision thread performs logistics (such as garbage collection) and other background tasks that may not contribute to the main work of the application but continue its main work for the application. Unlike the user thread, the supervision thread does not need to be completed before the application ends. When an application starts thread (which is a user thread), JVM checks if there is any other user thread that is running. If there is, JVM will prevent the application from ending. Otherwise, JVM will end the application regardless of whether the monitoring thread is running. When a thread calls a straw object's START () method, the new starting thread is a user thread. It is default. To create a thread as a supervision thread, the program must call a setDaemon (Boolean Isdaemon) method with a Boolean truth parameter before calling start (). Later, you can check if a thread is a supervision thread by calling the IsDaemon () method of THREAD. If it is a monitoring thread that returns a Boolean true value. In order to let you try the user and supervision thread, I wrote a USERDAEMONTHREADDEMO: Table 7. UserdaemonthreadDemo.java // UserdaemonthreadDemo.java Class UserdaemonthreadDemo { Public static void main (string [] args) { IF (args.length == 0) New mythread () .start (); Else { Mythread MT = new mythread (); Mt.SetDaemon (TRUE); Mt.start (); } Try { Thread.sleep (100); } Catch (InterruptedException E) { } } } Class mythread extends thread { Public void Run () { System.out.println ("daemon is" isdaemon ()); While (True); } } After compiling the code, run UserDaemonthreadDemo through the Java2 SDK Java command. If you do not use the command line parameters, such as Java UserDaemonthreadDemo, new mythread () .Start () is executed. This code snippet starts a user thread that prints the DAEMON IS FALSE before entering an infinite loop. (You must press Ctrl-C or a combination button that ends an unlimited loop.) Because the new thread is a user thread, the application remains running after the start of the thread. However, if you specify at least one command line parameter, such as Java UserDaemonThreadDemo X, Mt.SetDaemon (TRUE) is executed and the new thread will be a supervision thread. As a result, once the thread is started from 100 milliseconds, the new supervision thread will end. caveat If the thread starts to execute, call the setDaemon (Boolean Isdaemon) method, the setDaemon method will throw an ILLEGALTHREADSTATEEXCEPTION object. Runnable After learning the previous part, you may think that introducing multithreaded into a class always requires you to extend Thread and overload your subclass with the Thread's Run () method. However, it is not always a choice. Java enforces the inheritance of two or more superclars. As a result, if a class expands a wireless class, that class cannot extend Thread. If a limit, how can I introduce multiple threads into a class that has expanded other classes? Fortunately, Java designers have realized that it is impossible to create Thread subclasses. This results in generating a java.lang.Runnable interface and a Thread constructor with Runnable parameters, such as Thread (Runnable Target). The runnable interface declares a single method signature: Void Run (). This signature is the same as the thread's Run () method and as a thread's execution portal. Because runnable is an interface, any class can implement an interface by including an IMPLEMENTS clause to a class head and providing an appropriate Run () method. In execution time, program code can create an object or runnable from that class and pass the RunNable reference to a suitable Thread constructor. The constructor and the Thread object stored together this reference and ensures a new thread to call the run () method of runnable after calling the Thread object. Demonstration is true for Table 8: Table 8.RunnableDemo.java // RunnableDemo.java Class RunnableDemo { Public static void main (string [] args) { Rectangle R = New Rectangle (5, 6); R.DRAW (); // Different rectangles with the width and height of the random selection NEW Rectangle (); } } Abstract Class Shape { Abstract void Draw (); } Class Rectangle Extends Shape IMPLEments Runnable { Private int W, H; Rectangle () { // Create a new Thread object that binds this runnable and starts a call to call this runnable // Run () method thread New thread (this) .start (); } Rectangle (int W, INT H) { IF (W <2) Throw New IllegalarGumentexception ("w value" w "<2"); if (h <2) Throw New IllegalargumentException ("H Value" H "<2"); THIS.W = W; THIS.H = H; } Void Draw () { For (int C = 0; c System.out.print ('*'); System.out.print ('/ n'); For (int R = 0; R { System.out.print ('*'); For (int C = 0; c System.out.print (''); System.out.print ('*'); System.out.print ('/ n'); } For (int C = 0; c System.out.print ('*'); System.out.print ('/ n'); } Public void Run () { For (int i = 0; i <20; i ) { W = RND (30); IF (W <2) W = 2; H = rND (10); IF (h <2) H = 2; Draw (); } } INT RND (INT LIMIT) { // Returns a random number X within 0 <= x Return (int) ("math.random () * limited; } } RunnableDemo consists of class RunnableDemo, Shape, and Rectangle. Class RunnableDemo drives applications by creating a Rectangle object - by calling the object's DRAW () method - and the Rectangle class that is not made by creating the second. Instead, Shape and Rectangle constitute a SHAPE-based class. Shape is abstract because it provides an abstract draw () method. Various Shape classes, such as Rectangle, extended Shape, and describing how they draw their own overload DRAW (). In the future, I may decide to introduce some additional Shape classes, create a shape array, and ask each Shape element to draw itself by calling the shape DRAW () method. RunnableDemo is generated as a simple program without multi-threaded. Behind I decided to introduce multithreaded to Rectangle so I can use a variety of widths and highly painted rectangles. Because Rectangle extension Shape (for later polymorphism), I don't have other options that only let Rectangle implement runnable. Similarly, in the Rectangle () constructor, I have to bind a Rectangle Runnable to a new Thread object and call the Start () method of Thread () to start a new thread to call the Rectangle's Run () method draws rectangle. Because the new output of RunnableDemo included in this article is too long, I suggest you compile and run the program yourself. skill When you face a class that is not able to extend thread, you will choose which method you want to implement Runnable? If this class has expanded other classes, you must implement Runnable. However, if this class does not expand other classes, consider the name of the class. The name will suggest that the object of this class is not positive is negative. For example, Name Ticker suggests that it is positive. Therefore, the Ticker class will extend Thread, and the Ticker object will be used as a dedicated Thread object. Instead, Rectangle hints that the negative object -Rectangle object does not do anything to them. Therefore, the Rectangle class will implement RunNable, and the Rectangle object will use the Thread object (for test or other intentions) instead of becoming a dedicated Thread object. review The user expects the program to achieve excellent performance. One way is to complete those tasks with threads. A thread is an independent execution channel of a program code. Threads are beneficial to GUI-based procedures because they allow those programs to remain respond to users when performing other tasks. In addition, the threaded program is completely fast than the copies that have no threads. This is especially obvious for running on multi-processor machines, where each thread has its own processor. Thread and Thread subclass objects describe threads and related to those entities. For classes that cannot extend Thread, you have to create a runnable to utilize multithreaded advantages.