Java多线程学习笔记(一)

一、什么是多线程

首先是多线程的概念:

多线程是异步的,和单任务不同,并不一定按照代码的执行顺序(上图左)来运行,而是交错占用CPU运行(上图右);

二、如何使用多线程

 JAVA多线程有两种实现方式:1、继承Thread类; 2、实现Runnable接口

其中实现Runnable接口是Java多线程的主要实现方法,因为JAVA的单继承特性,一旦继承了Thread类,就不能再继承别的类。而JAVA类可以继承多个接口。

1、继承Thread类实现方法:

public class Thread extends Thread {
    @Override
    public void run(){
        //super.run(); 调用父类的run方法
        System.out.println("success!");
    }
}

public class Run {
    public static void main(String[] args) {
        Thread a = new Thread();
        a.start();
        System.out.println("end!");
    }
}

其中 @Override 是JAVA注解,代码重写一个父类的函数,继承Thread类实现多线程,必须重写 run() 方法。

问题一:为什么要写 super.run();既然是重写父类的 run() 方法为什么还要写 super.run() 呢?

首先是 Thread run()方法 源码:

 //Thread类重写了Runnable接口的run()方法。
//该run()方法首先判断当前是否有Runnable的实现target存在。 如果存在就执行target.run()

private Runnable target;
@Override
public void run() { if (target != null) { target.run(); } }

原来Thread类也是实现了Runnable接口;在run()方法中,首先会检查target是否为空,如果不是,则执行该target的run()方法。

首先上结论:

1、不管传入的Target是否为空,首先都会执行Thread自己的run()方法。如果重写了该方法且该方法中没有super.run(),那么是永远不会调用Runnable实现的run()方法;

2、如果没有重写该方法,则会去判断target是否为空,以此来决定调用target实现的run()方法;

3、如果重写了该方法,且该方法中有super.run(),在执行完该语句之前的所有代码后,会判断target是否为空,以此来决定调用target实现的run()方法

具体实验: https://blog.csdn.net/guguituzi/article/details/44593863

所以,super.run();正常情况下可以不写,但是我看到是书上都习惯性带上 super.run() ,知道为什么的小伙伴非常感谢能够给我留言告诉我答案。

问题二: .start() 源码

/*  JVM调用此线程的run方法。*/

 public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        //此判断当前线程只能被启动一次,不能被重复启动
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        /*通知组该线程即将启动
          *这样它就可以添加到组的线程列表中
         *并且该组的未启动计数可以递减。*/
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                // 如果线程启动失败,从线程组里面移除该线程
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

另外,线程名.start() 的顺序,不代表线程的执行顺序!

2、实现Runnable接口的实现方法:

public class Thread_2 implements Runnable{
    @Override
    public void run(){
        System.out.println("i'm running!...");
    }
}

实现原理和继承Thread类似,不再赘述。

猜你喜欢

转载自www.cnblogs.com/samanian/p/11822238.html
今日推荐