Java基础之线程——派生自Thread类的子类(TryThread)

时间:2023-01-03 17:31:13

控制台程序。

程序总是至少有一个线程,程序开始执行时就会创建这个线程。在普通的Java应用程序中,这个线程从mian()方法的开头启动。

要开始执行线程,可以调用Thread对象的start()方法。在新线程中执行的代码总是一个名为run()的方法,这是一个公共方法,不带参数,也没有返回值。程序中除了主线程之外的其他线程总是在表示线程的对象的run()方法中启动。

如果希望用于表示程序中线程的类执行某些操作,就必须为类实现run()方法,因为从Thread类继承的run()方法什么也不做。

重点:程序没有调用run()方法来启动线程,而是调用表示线程对象额start()方法,进而调用run()方法。

可以用以下两种方法来定义表示线程的类:

1、定义Thread的子类,提供run()方法的定义以重写继承而来的方法。

2、把自己的类定义为实现了Runnable()接口,这个接口声明了run()方法,之后再在需要时在自己的类中创建Thread对象。

下面为使用第一种方法:

 1 import java.io.IOException;
 2 
 3 public class TryThread extends Thread {
 4   public TryThread(String firstName, String secondName, long delay) {
 5     this.firstName = firstName;                                        // Store the first name
 6     this.secondName = secondName;                                      // Store the second name
 7     aWhile = delay;                                                    // Store the delay
 8     setDaemon(true);                                                   // Thread is daemon
 9   }
10 
11   public static void main(String[] args) {
12     // Create three threads
13     Thread first = new TryThread("Hopalong ", "Cassidy ", 200L);
14     Thread second = new TryThread("Marilyn ", "Monroe ", 300L);
15     Thread third = new TryThread("Slim ", "Pickens ", 500L);
16 
17     System.out.println("Press Enter when you have had enough...\n");
18     first.start();                                                     // Start the first thread
19     second.start();                                                    // Start the second thread
20     third.start();                                                     // Start the third thread
21 
22     try {
23       System.in.read();                                                // Wait until Enter key pressed
24       System.out.println("Enter pressed...\n");
25 
26     } catch (IOException e) {                                          // Handle IO exception
27       System.err.println(e);                                           // Output the exception
28     }
29     System.out.println("Ending main()");
30     return;
31   }
32 
33   // Method where thread execution will start
34   @Override
35   public void run() {
36     try {
37       while(true) {                                                    // Loop indefinitely...
38         System.out.print(firstName);                                   // Output first name
39         sleep(aWhile);                                                 // Wait aWhile msec.
40         System.out.print(secondName + "\n");                           // Output second name
41       }
42     } catch(InterruptedException e) {                                  // Handle thread interruption
43       System.out.println(firstName + secondName + e);                  // Output the exception
44     }
45   }
46 
47   private String firstName;                                            // Store for first name
48   private String secondName;                                           // Store for second name
49   private long aWhile;                                                 // Delay in milliseconds
50 }

当程序运行到System.in.read()语句时,会暂停等待用户通过键盘输入数据。用户可以输入一个或多个字符,然后按Enter键。System.in.read()语句只会读取第一个字符,然后继续运行下面的语句。

执行System.in.read()方法将从键盘缓冲区读入一个字节的数据,然而返回的却是16比特的整型量的低位字节是真正输入的数据,其高位字节全是零。当键盘缓冲区中没有未被读取的数据时,执行System.in.read()将导致系统转入阻塞(block)状态。在阻塞状态上,当前流程将停留在上述语句位置且整个程序被挂起,等待用户输入一个键盘数据后,才能继续运行下去;所以程序中有时利用System.in.read()语句来达到暂时保留屏幕的目地。

在TryThread构造函数中,用参数true调用setDaemon()方法会创建后台线程(Daemon Thread)。后台线程是从属于创建它的线程的背景线程,所以当创建它的线程结束时,后台线程也会结束。

用户线程拥有自己的生命周期,而且并不取决于创建它的线程。在创建它的线程结束后,用户线程可以继续执行。包含main()方法的默认线程是用户线程。

注意线程只有的启动前才能调用setDaemon()方法,如果在启动过线程后调用,setDaemon()方法就会抛出IllegalThreadStateException异常。

另外,由后台线程创建的线程也默认为后台线程。

注:daemon['di:mən] ['di:mən]

n.