Concurrence-6-Creating and Starting Java Threads


Creating and Starting Java Threads


##### 创建和启动java线程

文章的地址:翻译文章的源地址
java线程和java的其他的对象一样,也是一个对象。线程是 类 java.lang.Thread的实例或者这个类的子类的实例。除了作为对象外,java线程也可以执行代码。 在java中创建一个线程的代码如下:
Thread thread = new Thread();

启动这个线程的时候,我们可以向下面一样调用它的start()方法: thread.start();

这里例子中线程的执行过程中不会执行任何的代码,线程启动后会马上停止。
指定线程运行的过程执行的代码有两种的方法,第一种是创建一个Thread的子类,重载run()方法。第二种方法就是传一个实现Runnable接口的对象给Thread构建方法, 这两种方法,下面都有实例说明:
第一种方式指定一个线程执行的代码,就是创建一个Thread的子类,重载run()方法。当你调用start()方法之后,跟着就是run()方法的运行,代码如下:

  public class MyThread extends Thread {
    public void run(){
       System.out.println("MyThread running");
    }
  }

对于上面定义的线程,你可以通过如下的代码创建和启动线程。

  MyThread myThread = new MyThread();
  myTread.start();

start方法启动后,就会直接的返回,不会去等run方法调用完成之后再返回的。run方法就像是在另个的一个不同的CPU上面运行。在此理中, run方法的运行,会打印出”MyThread running”.

你也可以通过创建匿名类来创建线程,如下所示:

  Thread thread = new Thread(){
    public void run(){
      System.out.println("Thread Running");
    }
  }
  thread.start();

这里例子创建了一个新的线程,执行的时候,调用run方法,会打印出: “Thread running”

Runnable 接口的实现
第二种方式是指定线程执行代码的方式是:创建一个实现Runnable的接口的类,这个Runnable的对象可以被一个线程执行。 示例代码:

  public class MyRunnable implements Runnable {
    public void run(){
       System.out.println("MyRunnable running");
    }
  }

为了能够使用线程执行这个对象,我们把MyRunnable的一个实例传给线程的构造函数,如下代码:

   Thread thread = new Thread(new MyRunnable());
   thread.start();

当线程启动后,就会调用构造函数中的MyRunnable实例的run方法,上面的例子中就会打印:”MyRunnable running”.你也可以向下面一样 采用匿名实现Runnable的方式

Runnable myRunnable = new Runnable(){
     public void run(){
        System.out.println("Runnable running");
     }
   }
   Thread thread = new Thread(myRunnable);
   thread.start();

那我们是使用子类的方式还是接口实现的方式? 没有哪一个方式是最好的说法,个人认为,我比较喜欢实现接口Runnable的方式,使用一个线程调用实现接口的实例。因为当Runnable实现类被 线程池执行的时候,当线程池中一个线程位空闲的时候,Runnable实现类比较容易排成队(等候执行),这点比线程的子类来的简单。

有些时候,你可能必须的使用线程的子类。例如,创建一个线程的子类,可以执行不止一个的Runnable实例,典型的场景就是线程池的实现。

常见的陷阱:调用run方法而不是start方法 当创建和启动一个线程常见的一个错误就是调用run方法而不去调用start方法,例如:

  Thread newThread = new Thread(MyRunnable());
  thread.run();  //should be start();

刚开始的时候你可能注意不到什么,因为调用run方法的执行结果和start一样,就如你所预料的。然而它并不是被你创建的线程执行的,它是被创建的线程的实例 执行的,换句话说,上面的thread执行run方法,就是直接的调用新建的MyRunnable()实例的run方法。如果想要线程调用,你必须执行start方法。

线程名称
当你常见一个线程的时候,你可以给它起一个名称,这个名称能够使你区分不同的线程。例如,当多个线程像System.out中写数据的时候,我们可以区分到底 是哪一个线程所写的文本,下面就是一个例子:

   Thread thread = new Thread("New Thread") {
      public void run(){
        System.out.println("run by: " + getname());
      }
   };
   thread.start();
   System.out.println(thread.getName());

注意到 字符串”New Thread”作为参数被传入了Thread的构造函数,传入的这个字符串就是线程的名称,这个名称可以通过Thread的getName方法获得。 你也可以在实现Runnable接口的方式中,传入线程的名称,代码如下:

   MyRunnable runnable = new MyRunnable();
   Thread thread = new Thread(runnable, "New Thread");
   thread.start();
   System.out.println(thread.getName());

一个取得当前执行线程名称的方式是:

   String threadName = Thread.currentThread().getName();

java线程的例子:

public class ThreadExample {
  public static void main(String[] args){
    System.out.println(Thread.currentThread().getName());
    for(int i=0; i<10; i++){
      new Thread("" + i){//设置线程的名称
        public void run(){
          System.out.println("Thread: " + getName() + " running");
        }
      }.start();
    }
  }
}

注意:线程的启动是按照顺序进行启动的,但是她们的执行顺序可能不是顺序的。第一个线程可能并不是第一个执行的,并不是第一个打印 出自己名称的线程,线程的执行是并发的,执行的顺序是有JVM或者操作系统决定的,它们执行的顺序和启动的顺序并不是一致的。



上一篇  Concurrency-7-Race Conditions and Critical Sections 下一篇   自我的认知