Java多线程3:Thread中的实例方法 [Java] Thread的start()和run()函数区别

一、Thread类中的方法调用方式

  学习Thread类中的方法是学习多线程的第一步。在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别:

  1、this.XXX()

  这种调用方式表示的线程是线程实例本身

  2、Thread.currentThread.XXX()或Thread.XXX()

  上面两种写法是一样的意思。这种调用方式表示的线程是正在执行Thread.currentThread.XXX()所在代码块的线程

  当然,这么说,肯定有人不理解两者之间的差别。没有关系,之后会讲清楚,尤其是在讲Thread构造函数这块。讲解后,再回过头来看上面2点,会加深理解。

二、Thread类中的实例方法

  从Thread类中的实例方法和类方法的角度讲解Thread中的方法,这种区分的角度也有助于理解多线程中的方法。实例方法,只和实例线程(也就是new出来的线程)本身挂钩,和当前运行的是哪个线程无关。看下Thread类中的实例方法:

  1、start()方法

  start()方法的作用讲得直白点就是通知"线程规划器",此线程可以运行了,正在等待CPU调用线程对象的run()方法,产生一个异步执行的效果。

  举例:

public class Thread01 implements Runnable{

    @Override
    public void run() {
        for(int i = 0; i < 5; i++) {
            try {
                Thread.sleep((int) Math.random() * 5000);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Thread01();
        Thread thread = new Thread(runnable);
        thread.start();
        for(int i = 0; i < 5; i++) {
            try {
                Thread.sleep((int) Math.random() * 5000);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

  第一次运行结果:

Thread-0
main
Thread-0
main
Thread-0
main
Thread-0
main
Thread-0
main

  第二次运行结果:

main
Thread-0
main
Thread-0
main
Thread-0
Thread-0
Thread-0
main
main

  可以看到,CPU调用哪个线程具有不确定性。再举例说明start()方法的顺序是否就是线程启动的顺序?

public class Thread01 implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Thread01();
        //创建线程1
        Thread thread1 = new Thread(runnable);
        //创建线程2
        Thread thread2 = new Thread(runnable);
        //创建线程3
        Thread thread3 = new Thread(runnable);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

  第一次运行的结果:

Thread-1
Thread-0
Thread-2

  第二次运行的结果:

Thread-2
Thread-0
Thread-1

  尽管启动线程的顺序是thread1,thread2,thread3,但是被调用的顺序却不是按照启动顺序来的。即:调用start()方法的顺序不代表线程的启动顺序,线程的启动顺序具有不确定性。

  2、run()方法

  线程开始执行,虚拟机调用的是线程run()方法中的内容,当线程没有通过start()方法让其处于被调用状态的时候,其线程的run()方法不会被执行的。但是如果直接通过.run()来调用的话,还是可以调用的到,但这个时候run()方法所在线程就是主线程了,仅仅只是一个普通方法而已,不在充当线程中的run()方法的作用。

  举例:通过.start()方法获取run()方法所在的线程

public class Thread01 implements Runnable{
    @Override
    public void run() {
        System.out.println("run方法所在的线程为:" + Thread.currentThread().getName());
    }
}
public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Thread01();
        //创建线程
        Thread thread1 = new Thread(runnable);
        thread1.start();
    }
}

  结果:

run方法所在的线程为:Thread-0

  可以看到run()方法所在的线程就是我们创建的线程,而不再main主线程内。

  通过.run()方法获取run()方法所在的线程

public class Thread01 implements Runnable{
    @Override
    public void run() {
        System.out.println("run方法所在的线程为:" + Thread.currentThread().getName());
    }
}
public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Thread01();
        //创建线程
        Thread thread1 = new Thread(runnable);
        thread1.run();
    }
}

  结果:

run方法所在的线程为:main

  可以看到,此时run()方法所在的线程就是main主线程,而不再是我们自己创建的那个线程。

  所以,通过start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。不通过start()方法来直接调用的话,run()方法只是thread的一个普通方法,还是在主线程里执行。

参考资料:

  [Java] Thread的start()和run()函数区别

猜你喜欢

转载自www.cnblogs.com/zfyang2429/p/10515306.html