1、在 Java 中创建线程有两种方法:使用 Thread 类和使用 Runnable 接口。在使用 Runnable接口时需要建立一个 Thread 实例。因此,无论是通过 Thread 类还是 Runnable 接口建立线程,都必须建立 Thread 类或它的子类的实例。Thread 类的构造方法被重载了八次,构造方法如下:public Thread( ); public Thread(Runnable target); public Thread(String name); public Thread(Runnable target, String name); public Thread(
2、ThreadGroup group, Runnable target); public Thread(ThreadGroup group, String name); public Thread(ThreadGroup group, Runnable target, String name); public Thread(ThreadGroup group, Runnable target, String name, long stackSize); Runnable target实现了 Runnable 接口的类的实例。要注意的是 Thread 类也实现了 Runnable 接口,因此,从
3、Thread 类继承的类的实例也可以作为 target 传入这个构造方法。String name线程的名子。这个名子可以在建立 Thread 实例后通过 Thread 类的 setName 方法设置。如果不设置线程的名子,线程就使用默认的线程名:Thread-N,N 是线程建立的顺序,是一个不重复的正整数。ThreadGroup group当前建立的线程所属的线程组。如果不指定线程组,所有的线程都被加到一个默认的线程组中。关于线程组的细节将在后面的章节详细讨论。long stackSize线程栈的大小,这个值一般是 CPU 页面的整数倍。如 x86 的页面大小是 4KB.在 x86平台下,默认
4、的线程栈大小是 12KB.一个普通的 Java 类只要从 Thread 类继承,就可以成为一个线程类。并可通过Thread 类的 start 方法来执行线程代码。虽然 Thread 类的子类可以直接实例化,但在子类中必须要覆盖 Thread 类的 run 方法才能真正运行线程的代码。下面的代码给出了一个使用 Thread 类建立线程的例子:001 package mythread; 002 003 public class Thread1 extends Thread 004 005 public void run() 006 007 System.out.println(this.getNa
5、me(); 008 009 public static void main(String args) 010 011 System.out.println(Thread.currentThread().getName(); 012 Thread1 thread1 = new Thread1(); 013 Thread1 thread2 = new Thread1 (); 014 thread1.start(); 015 thread2.start(); 016 017 上面的代码建立了两个线程:thread1 和 thread2.上述代码中的 005 至 008 行是Thread1 类的 ru
6、n 方法。当在 014 和 015 行调用 start 方法时,系统会自动调用 run 方法。在 007 行使用 this.getName()输出了当前线程的名字,由于在建立线程时并未指定线程名,因此,所输出的线程名是系统的默认值,也就是 Thread-n 的形式。在 011 行输出了主线程的线程名。上面代码的运行结果如下:main Thread-0 Thread-1从上面的输出结果可以看出,第一行输出的 main 是主线程的名子。后面的 Thread-1和 Thread-2 分别是 thread1 和 thread2 的输出结果。注意:任何一个 Java 程序都必须有一个主线程。一般这个主线
7、程的名子为 main.只有在程序中建立另外的线程,才能算是真正的多线程程序。也就是说,多线程程序必须拥有一个以上的线程。Thread 类有一个重载构造方法可以设置线程名。除了使用构造方法在建立线程时设置线程名,还可以使用 Thread 类的 setName 方法修改线程名。要想通过 Thread 类的构造方法来设置线程名,必须在 Thread 的子类中使用 Thread 类的 public Thread(String name)构造方法,因此,必须在 Thread 的子类中也添加一个用于传入线程名的构造方法。下面的代码给出了一个设置线程名的例子:001 package mythread; 00
8、2 003 public class Thread2 extends Thread 004 005 private String who; 006 007 public void run() 008 009 System.out.println(who + “:“ + this.getName(); 010 011 public Thread2(String who) 012 013 super(); 014 this.who = who; 015 016 public Thread2(String who, String name) 017 018 super(name); 019 this
9、.who = who; 020 021 public static void main(String args) 022 023 Thread2 thread1 = new Thread2 (“thread1“, “MyThread1“); 024 Thread2 thread2 = new Thread2 (“thread2“); 025 Thread2 thread3 = new Thread2 (“thread3“); 026 thread2.setName(“MyThread2“); 027 thread1.start(); 028 thread2.start(); 029 threa
10、d3.start(); 030 031在类中有两个构造方法:第 011 行:public sample2_2(String who)这个构造方法有一个参数:who.这个参数用来标识当前建立的线程。在这个构造方法中仍然调用 Thread 的默认构造方法 public Thread( )。第 016 行:public sample2_2(String who, String name)这个构造方法中的 who 和第一个构造方法的 who 的含义一样,而 name 参数就是线程的名名。在这个构造方法中调用了 Thread 类的 public Thread(String name)构造方法,也就是第
11、018 行的 super(name)。在 main 方法中建立了三个线程:thread1、thread2 和 thread3.其中 thread1 通过构造方法来设置线程名,thread2 通过 setName 方法来修改线程名,thread3 未设置线程名。运行结果如下:thread1:MyThread1 thread2:MyThread2 thread3:Thread-2从上面的输出结果可以看出,thread1 和 thread2 的线程名都已经修改了,而thread3 的线程名仍然为默认值:Thread-2.thread3 的线程名之所以不是 Thread-1,而是 Thread-2,这
12、是因为在 024 行建立 thread2 时已经将 Thread-1 占用了,因此,在 025行建立 thread3 时就将 thread3 的线程名设为 Thread-2.然后在 026 行又将 thread2 的线程名修改为 MyThread2.因此就会得到上面的输出结果。注意:在调用 start 方法前后都可以使用 setName 设置线程名,但在调用 start 方法后使用 setName 修改线程名,会产生不确定性,也就是说可能在 run 方法执行完后才会执行 setName.如果在 run 方法中要使用线程名,就会出现虽然调用了 setName 方法,但线程名却未修改的现象。Thread 类的 start 方法不能多次调用,如不能调用两次 thread1.start()方法。否则会抛出一个 IllegalThreadStateException 异常。