共计 3175 个字符,预计需要花费 8 分钟才能阅读完成。
在 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(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 接口,因而,从 Thread 类继承的类的实例也能够作为 target 传入这个构造方法。
String name
线程的名子。这个名子能够在建设 Thread 实例后通过 Thread 类的 setName 办法设置。如果不设置线程的名子,线程就应用默认的线程名:Thread-N,N 是线程建设的程序,是一个不反复的正整数。
ThreadGroup group
以后建设的线程所属的线程组。如果不指定线程组,所有的线程都被加到一个默认的线程组中。对于线程组的细节将在前面的章节具体探讨。
long stackSize
线程栈的大小,这个值个别是 CPU 页面的整数倍。如 x86 的页面大小是 4KB。在 x86 平台下,默认的线程栈大小是 12KB。
一个一般的 Java 类只有从 Thread 类继承,就能够成为一个线程类。并可通过 Thread 类的 start 办法来执行线程代码。尽管 Thread 类的子类能够间接实例化,但在子类中必须要笼罩 Thread 类的 run 办法能力真正运行线程的代码。上面的代码给出了一个应用 Thread 类建设线程的例子:
复制代码 代码如下:
package mythread;
public class Thread1 extends Thread
{public void run()
{System.out.println(this.getName());
}
public static void main(String[] args)
{System.out.println(Thread.currentThread().getName());
Thread1 thread1 = new Thread1();
Thread1 thread2 = new Thread1 ();
thread1.start();
thread2.start();}
}
下面的代码建设了两个线程:thread1 和 thread2。上述代码中的 005 至行是 Thread1 类的 run 办法。当在 014 和 015 行调用 start 办法时,零碎会主动调用 run 办法。在 007 行应用 this.getName() 输入了以后线程的名字,因为在建设线程时并未指定线程名,因而,所输入的线程名是零碎的默认值,也就是 Thread- n 的模式。在 011 行输入了主线程的线程名。
下面代码的运行后果如下:
main
Thread-0
Thread-1
从下面的输入后果能够看出,第一行输入的 main 是主线程的名子。前面的 Thread- 1 和 Thread- 2 别离是 thread1 和 thread2 的输入后果。
留神:任何一个 Java 程序都必须有一个主线程。个别这个主线程的名子为 main。只有在程序中建设另外的线程,能力算是真正的多线程程序。也就是说,多线程程序必须领有一个以上的线程。
Thread 类有一个重载构造方法能够设置线程名。除了应用构造方法在建设线程时设置线程名,还能够应用 Thread 类的 setName 办法批改线程名。要想通过 Thread 类的构造方法来设置线程名,必须在 Thread 的子类中应用 Thread 类的 public Thread(String name) 构造方法,因而,必须在 Thread 的子类中也增加一个用于传入线程名的构造方法。上面的代码给出了一个设置线程名的例子:
复制代码 代码如下:
package mythread;
public class Thread2 extends Thread
{
private String who;
public void run()
{System.out.println(who + ":" + this.getName());
}
public Thread2(String who)
{super();
this.who = who;
}
public Thread2(String who, String name)
{super(name);
this.who = who;
}
public static void main(String[] args)
{Thread2 thread1 = new Thread2 ("thread1", "MyThread1");
Thread2 thread2 = new Thread2 ("thread2");
Thread2 thread3 = new Thread2 ("thread3");
thread2.setName("MyThread2");
thread1.start();
thread2.start();
thread3.start();}
在类中有两个构造方法:
第 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) 构造方法,也就是第 018 行的 super(name)。
在 main 办法中建设了三个线程:thread1、thread2 和 thread3。其中 thread1 通过构造方法来设置线程名,thread2 通过 setName 办法来批改线程名,thread3 未设置线程名。
运行后果如下:
复制代码 代码如下:
thread1:MyThread1
thread2:MyThread2
thread3:Thread-1
从下面的输入后果能够看出,thread1 和 thread2 的线程名都曾经批改了,而 thread3 的线程名依然为默认值:Thread-1。thread3 的线程名之所以不是 Thread-2,而是 Thread-1,这是因为在 026 行曾经指定了 thread2 的 Name,因而,启动 thread3 时就将 thread3 的线程名设为 Thread-1。因而就会失去下面的输入后果。
留神:在调用 start 办法前后都能够应用 setName 设置线程名,但在调用 start 办法后应用 setName 批改线程名,会产生不确定性,也就是说可能在 run 办法执行完后才会执行 setName。如果在 run 办法中要应用线程名,就会呈现尽管调用了 setName 办法,但线程名却未修改的景象。
Thread 类的 start 办法不能屡次调用,如不能调用两次 thread1.start() 办法。否则会抛出一个 IllegalThreadStateException 异样。