线程的创建和启用

一、通过继承Thread类来创建线程

1、继承Thread,重写run方法,run方法的方法体就代表了县城需要执行的任务

2、创建Thread子类实例,即创建了线程对象

3、调用线程对象.start()方法,启动该线程 

//通过继承Thread类来创建线程

publicclass FirstThread extends Thread
{
       private int i;

       //重写run方法,run方法的方法体就是线程的执行体

       public void run
       {
              for(i;i<100;i++)
              {
                     //继承Thread后,可通过getName()直接返回当前线程名;this用于获取当前线程

                     System.out.println(getName()+""+i);
              }            
       }      
}

publicstatic void main(String[] args)
{
       for(int i;i<100,i++)
       {

              //调用Thread的currentThread,currentThread用来获取当前正在执行的线程

              System.out.println(Thread.currentThread().getName()+""+i);

              if(i==20 ) //当i=20时,以下两条线程被创建、启动
              {
                     //创建并启动第一条线程

                     new FirstThread().start();

                     //创建并启动第二条线程

                     new FirstThread().start();                    
              }             

       }

}
二、通过实现Runnable接口创建线程

1、实现Runnable接口,实现run方法

2、通过newThread(st,"新线程1").start();创建并启动线程 

//通过实现Runnable接口创建线程

publicclass SecondThread implements Runnable
{
       private int i;
       //重写run方法,run方法的方法体就是线程的执行体
       public void run
       {
              for(i;i<100;i++)
              {
                    //继承Thread后,只能通过currentThread获得当前线程

                     System.out.println(Thread.currentThread().getName()+""+i)
              }             
       }      
}
publicstatic void main(String[] args)
{
       for(int i;i<100,i++)
       {             
              System.out.println(Thread.currentThread().getName()+""+i);

              if(i==20)
              {
                     //通过newThread(target,name)来创建并启动第一条线程

                     new Thread(st,"新线程1").start();

                     //通过newThread(target,name)来 创建并启动第二条线程

                     new Thread(st,"新线程2").start();
              }
              if(i>20 &&!st.isAlive())//isAlive判断线程状态,死亡态返回false
              {
                    //试图再次启动该线程

                     st.start();
              }
       }
}

通过实现Runnable接口创建的线程SecondThread并非真正的线程对象,只能作为线程对象的target目标,实际上的线程是target类,创建的多条线程共享线程类target实例的属性方法;

而使用第一种方法继承Thread类所创建的线程就是线程对象本身。所以用this可以直接表示当前线程对象。

三、两种创建线程方式对比

创建方式

优点

缺点

实现Runnable接口(常用)

1、   还可继承其他类

2、   多线程共享一个target对象,所以非常适合多个相同线程处理同一份资源

编程相对复杂,必须使用Thread.currentThread()获取当前线程

实现Thread类

编写简单,直接this便可获得当前线程

已经继承Thread,故无法继承其它父类

线程生命周期

New

——》新建状态,java虚拟机分配内存,初始化成员变量——》

Start

——》就绪状态,虚拟机为齐创建方法调用栈,准备就绪,等待运行——》虚拟机通过线程调度,确定执行哪个就绪态线程——》

Run

——》获得CPU,开始执行run方法的方法体——》运行状态——》

Blocked

——》当一条线称运行时,它不可能一致霸占CPU,在运行过程中需要被中断,使其它线程也有机会运行——》被中断的线程进入阻塞状态——》

Dead

——》run()方法体执行完毕,线程结束——》死亡状态

注意:

  1. 一个线程只能调用一次start()方法,启用一次,死亡后也无法再次运行,故一条线程在其生命周期里只有一次调用start的机会。
  2. 启用线程调用start ,而非run,直接调用线程类的run方法,该方法立刻执行,在返回之前,其它线程无法并行执行。类似于执行一个类的普通方法,而非执行线程执行体,所以起不到多线程高校并发执行的效果。
  3. 死亡可为run方法执行完毕,或者线程直接抛异常,还可直接调用该线程的stop()方法结束该线程;但最后一种方式容易导致死锁,通常不推荐使用。