在Java中创建线程有两种方法使用Thread类和使用Runnable接口在使用Runnable接口时需要建立一个Thread实例因此无论是通过Thread类还是Runnable接口建立线程都必须建立Thread类或它的子类的实例Thread类的构造方法被重载了八次构造方法如下
publicThread();
publicThread(Runnabletarget);
publicThread(Stringname);
publicThread(RunnabletargetStringname);
publicThread(ThreadGroupgroupRunnabletarget);
publicThread(ThreadGroupgroupStringname);
publicThread(ThreadGroupgroupRunnabletargetStringname);
publicThread(ThreadGroupgroupRunnabletargetStringnamelongstackSize);
Runnable target
实现了Runnable接口的类的实例要注意的是Thread类也实现了Runnable接口因此从Thread类继承的类的实例也可以作为target传入这个构造方法
String name
线程的名子这个名子可以在建立Thread实例后通过Thread类的setName方法设置如果不设置线程的名子线程就使用默认的线程名ThreadNN是线程建立的顺序是一个不重复的正整数
ThreadGroup group
当前建立的线程所属的线程组如果不指定线程组所有的线程都被加到一个默认的线程组中关于线程组的细节将在后面的章节详细讨论
long stackSize
线程栈的大小这个值一般是CPU页面的整数倍如x的页面大小是KB在x平台下默认的线程栈大小是KB
一个普通的Java类只要从Thread类继承就可以成为一个线程类并可通过Thread类的start方法来执行线程代码虽然Thread类的子类可以直接实例化但在子类中必须要覆盖Thread类的run方法才能真正运行线程的代码下面的代码给出了一个使用Thread类建立线程的例子
packagemythread;
publicclassThreadextendsThread
{
publicvoidrun()
{
Systemoutprintln(thisgetName());
}
publicstaticvoidmain(String[]args)
{
Systemoutprintln(ThreadcurrentThread()getName());
Threadthread=newThread();
Threadthread=newThread();
threadstart();
threadstart();
}
}
上面的代码建立了两个线程thread和thread上述代码中的至行是Thread类的run方法当在和行调用start方法时系统会自动调用run方法在行使用thisgetName()输出了当前线程的名字由于在建立线程时并未指定线程名因此所输出的线程名是系统的默认值也就是Threadn的形式在行输出了主线程的线程名
上面代码的运行结果如下
main
Thread
Thread
从上面的输出结果可以看出第一行输出的main是主线程的名子后面的Thread和Thread分别是thread和thread的输出结果
注意任何一个Java程序都必须有一个主线程一般这个主线程的名子为main只有在程序中建立另外的线程才能算是真正的多线程程序也就是说多线程程序必须拥有一个以上的线程
Thread类有一个重载构造方法可以设置线程名除了使用构造方法在建立线程时设置线程名还可以使用Thread类的setName方法修改线程名要想通过Thread类的构造方法来设置线程名必须在Thread的子类中使用Thread类的public Thread(String name)构造方法因此必须在Thread的子类中也添加一个用于传入线程名的构造方法下面的代码给出了一个设置线程名的例子
packagemythread;
publicclassThreadextendsThread
{
privateStringwho;
publicvoidrun()
{
Systemoutprintln(who+:+thisgetName());
}
publicThread(Stringwho)
{
super();
thiswho=who;
}
publicThread(StringwhoStringname)
{
super(name);
thiswho=who;
}
publicstaticvoidmain(String[]args)
{
Threadthread=newThread(threadMyThread);
Threadthread=newThread(thread);
Threadthread=newThread(thread);
threadsetName(MyThread);
threadstart();
threadstart();
threadstart();
}
在类中有两个构造方法
第行public sample_(String who)
这个构造方法有一个参数who这个参数用来标识当前建立的线程在这个构造方法中仍然调用Thread的默认构造方法public Thread( )
第行public sample_(String who String name)
这个构造方法中的who和第一个构造方法的who的含义一样而name参数就是线程的名名在这个构造方法中调用了Thread类的public Thread(String name)构造方法也就是第行的super(name)
在main方法中建立了三个线程threadthread和thread其中thread通过构造方法来设置线程名thread通过setName方法来修改线程名thread未设置线程名
运行结果如下
thread:MyThread
thread:MyThread
thread:Thread
从上面的输出结果可以看出thread和thread的线程名都已经修改了而thread的线程名仍然为默认值Threadthread的线程名之所以不是Thread而是Thread这是因为在行建立thread时已经将Thread占用了因此在行建立thread时就将thread的线程名设为Thread然后在行又将thread的线程名修改为MyThread因此就会得到上面的输出结果
注意在调用start方法前后都可以使用setName设置线程名但在调用start方法后使用setName修改线程名会产生不确定性也就是说可能在run方法执行完后才会执行setName如果在run方法中要使用线程名就会出现虽然调用了setName方法但线程名却未修改的现象
Thread类的start方法不能多次调用如不能调用两次threadstart()方法否则会抛出一个IllegalThreadStateException异常