欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java线程之用Thread类创建线程的方法

程序员文章站 2023-12-05 21:09:16
在java中创建线程有两种方法:使用thread类和使用runnable接口。在使用runnable接口时需要建立一个thread实例。因此,无论是通过thread类还是r...

在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至008行是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-2

从上面的输出结果可以看出,thread1和thread2的线程名都已经修改了,而thread3的线程名仍然为默认值:thread-2.thread3的线程名之所以不是thread-1,而是thread-2,这是因为在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异常。