在Java中有两种创建线程的方法:使用Thread类和使用Runnable接口。使用Runnable接口时,需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口创建线程,都必须创建Thread类或其子类的实例。Thread类的构造方法重载了八次,构造方法如下:复制代码代码如下:publicThread();publicThread(Runnabletarget);publicThread(Stringname);publicThread(可运行目标,字符串名称);publicThread(ThreadGroupgroup,Runnabletarget);publicThread(ThreadGroupgroup,Stringname);publicThread(ThreadGroupgroup,Runnabletarget,Stringname);publicThread(ThreadGroupgroup,Runnabletarget,Stringname,longstackSize);Runnabletarget实现Runnable接口的类的实例。需要注意的是Thread类也实现了Runnable接口,所以从Thread类继承的类的实例也可以作为目标传入这个构造函数。Stringname线程的名称。这个名字可以在Thread实例创建之后通过Thread类的setName方法来设置。如果没有设置线程名,线程会使用默认的线程名:Thread-N,N是线程的创建顺序,是一个不重复的正整数。ThreadGroupgroup当前建立的线程所属的线程组。如果未指定线程组,则所有线程都添加到默认线程组。关于线程组的细节将在后面的章节中详细讨论。longstackSize线程栈的大小,这个值一般是CPUpage的整数倍。例如,x86的页面大小为4KB。在x86平台上,默认线程堆栈大小为12KB。一个普通的Java类只要继承Thread类就可以成为线程类。而线程代码可以通过Thread类的start方法来执行。Thread类的子类虽然可以直接实例化,但是必须在子类中重写Thread类的run方法才能真正运行线程的代码。下面的代码给出了一个使用Thread类创建线程的例子:复制代码代码如下:packagemythread;publicclassThread1extendsThread{publicvoidrun(){System.out.println(this.getName());}publicstaticvoidmain(String[]args){System.out.println(Thread.currentThread().getName());Thread1thread1=newThread1();Thread1thread2=newThread1();thread1.start();thread2.start();}}上面的代码创建了两个线程:thread1和thread2。上面代码中第005行到第005行是Thread1类的run方法。当014、015行调用start方法时,系统会自动调用run方法。在007行,this.getName()用于输出当前线程的名称。由于创建线程时没有指定线程名,所以输出的线程名是系统的默认值,形式为Thread-n。011行输出了主线程的线程名,上面代码运行结果如下:mainThread-0Thread-1从上面的输出可以看出,第一行输出的是主线程的线程名主线程。下面的Thread-1和Thread-2分别是thread1和thread2的输出结果。注意:任何Java程序都必须有一个主线程。一般这个主线程的名字是main。只有在程序中建立了另一个线程,才能算是真正的多线程程序。也就是说,一个多线程程序必须有多个线程。Thread类有一个重载的构造函数来设置线程名称。除了在创建线程时使用构造函数设置线程名称外,还可以使用Thread类的setName方法修改线程名称。通过Thread类的构造函数设置线程名称,必须在Thread的子类中使用Thread类的publicThread(Stringname)构造函数。因此,在Thread的子类中也必须增加一个,传入线程名构造函数。下面的代码给出了设置线程名称的例子:复制代码代码如下:packagemythread;publicclassThread2extendsThread{privateStringwho;publicvoidrun(){System.out.println(who+":"+this.getName());}publicThread2(Stringwho){super();this.who=who;}publicThread2(Stringwho,字符串名称){super(name);this.who=who;}publicstaticvoidmain(String[]args){Thread2thread1=newThread2("thread1","MyThread1");Thread2thread2=newThread2("thread2");Thread2thread3=newThread2("thread3");thread2.setName("MyThread2");thread1.start();thread2.start();thread3.start();}类中有两个构造方法:Line011:publicsample2_2(Stringwho)这个构造方法有一个参数:who。该参数用于标识当前创建的线程。在这个构造方法中,仍然调用了Thread默认的构造方法publicThread()。016行:publicsample2_2(Stringwho,Stringname)构造方法中的who与第一种构造方法中的who含义相同,name参数为线程名称。在这个构造方法中,调用了Thread类的publicThread(Stringname)构造方法,也就是018行的super(name)。main方法中建立了三个线程:thread1、thread2和thread3。其中thread1通过构造方法设置线程名,thread2通过setName方法修改线程名,thread3不设置线程名。运行结果如下:复制代码代码如下:thread1:MyThread1thread2:MyThread2thread3:Thread-1从上面的输出结果可以看出修改了thread1和thread2的线程名,线程thread3的名称仍然是默认值:Thread-1。之所以thread3的线程名称不是Thread-2而是Thread-1,是因为在026行已经指定了thread2的Name,所以在启动thread3的时候,线程thread3的名称设置为Thread-1。因此,会得到上面的输出。注意:在调用start方法前后都可以使用setName来设置线程名称,但是在调用start方法之后使用setName修改线程名称会造成不确定性,也就是说setName可能要等到run方法执行后才会执行.如果要在run方法中使用线程名,会出现虽然调用了setName方法,但线程名并没有被修改的现象。Thread类的start方法不能调用多次,比如thread1.start()方法不能调用两次。否则将抛出IllegalThreadStateException。
