认识多线程中start和run方法的区别?

2019-04-12 09:25:54来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

一、认识多线程中的 start() 和 run()

1。start():

    先来看看Java API中对于该方法的介绍:

     使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

     结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。

     多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。

用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体中的代码执行完毕而直接继续执行后续的代码。通过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里的run()方法 称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。

2。run():

同样先看看Java API中对该方法的介绍:

      如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

    Thread 的子类应该重写该方法。

run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

3。总结:

调用start方法方可启动线程,而run方法只是thread类中的一个普通方法调用,还是在主线程里执行。

二、代码实例:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String args[]) {
        Thread t = new Thread() {
            public void run() {
                pong();
            }
        };
        t.start();
        System.out.print("ping");
    }
 
    static void pong() {
        System.out.print("pang");
    }

输出结果: pingpang

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String args[]) {
        Thread t = new Thread() {
            public void run() {
                pong();
            }
        };
        t.run();
        System.out.print("ping");
    }
 
    static void pong() {
        System.out.print("pang");
    }

输出结果:pongpang

 

通过以上两个程序实例,可以很容易的区分出start()方法和run()方法的区别:

t.start(); 该行代码相当于是启动线程,

t.run(); 该行代码相当于是使用t这个类中的run方法而已.

三、线程状态说明:

线程状态从大的方面来说,可归结为:初始状态可运行状态不可运行状态消亡状态,具体可细分为上图所示7个状态,说明如下:

1)线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但不管怎样,当我们new了Thread实例后,线程就进入了初始状态

2)当该对象调用了start()方法,就进入可运行状态

3)进入可运行状态后,当该对象被操作系统选中,获得CPU时间片就会进入运行状态

4)进入运行状态后涉及的情况就比较多,大致有如下情形: ﹒run()方法或main()方法结束后,线程就进入终止状态; 当线程调用了自身的sleep()方法或其他线程的join()方法,就会进入阻塞状态(该状态虽停止当前线程,但并不释放所占有的资源)。当sleep()结束或join()结束后,该线程进入可运行状态,继续等待OS分配时间片; 当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被锁住(synchroniza,lock),将会立即进入锁池状态,等待获取锁标记(这时的锁池里也许已经有了其他线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获得锁标记后,就转入可运行状态,等待OS分配 CPU时间片; 当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒(由于notify()只是唤醒一个线程,但我们由于不能确定具体唤醒的是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池,等待获取锁标记。 当线程调用stop方法,即可使线程进入消亡状态,但是由于stop方法是不安全的,不鼓励使用,大家可以通过run方法里的条件变通实现线程的 stop。

 

安全终止线程的自定义方法:

public class SafeStopThread implements Runnable{

   //定义线程终止的开关
  private volatile boolean stop=false;//此变量必须加上volatile
  int a=0;
  @Override
  public void run() {
    // TODO Auto-generated method stub
    while(!stop){
      synchronized ("") {
      a++;
      try {
        Thread.sleep(100);
      } catch (Exception e) {
        // TODO: handle exception
      }
      a--;
      String tn=Thread.currentThread().getName();
      System.out.println(tn+":a="+a);

    }
   }
  //线程终止方法
   public void threadStop(){
      stop=true;
   }
   public static void main(String[] args) {
       SafeStopThread t=new SafeStopThread();
       Thread t1=new Thread(t);
       t1.start();
       for(int i=0;i<5;i++){
           new Thread(t).start();
       }
       t.threadStop();//改变终止线程的状态
   }

 }

线程安全终止:https://blog.csdn.net/lexang1/article/details/49819347

好文转载学习自:https://www.cnblogs.com/whyalwaysme/p/4495959.html


原文链接:https://www.cnblogs.com/zhaosq/p/10564698.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Doclever 接口mock 操作

下一篇:jvm分析与调优+调优标准