Thread&Runable

Thread

public class Thread implements Runnable{

}

Thread构造方法

  //无参构造方法,自动生成name
  public Thread()
  //字符串构造方法,传入一个字符串给线程命名
  //可以用Thread类的get/setName方法对name进行访问和修改
  public Thread(String name)
  //传入Runnable接口实现
  public Thread(Runnable target)
  //传入一个线程组、一个Runnable接口实现
  //其中线程组中的基本单元既可以是线程也可以是线程组,进而组成一棵线程树
//除初始线程组之外,每个线程组有一个父线程
  public Thread(ThreadGroup group, Runnable target)
  //传入线程组、线程名
  public Thread(ThreadGroup group, String name)
  //传入Runnable接口实现,传入线程名
  public Thread(Runnable target, String name)
  //线程组、线程名、Runnable接口实现三者都传入
  public Thread(ThreadGroup group, Runnable target, String name)
  //多了一个stackSize,用于指定该线程申请的堆栈大小,不指定时默认为0
  //对于stackSize这个值如何使用,则由虚拟机自行决定
  //有些虚拟机会忽略这个值
  public Thread(ThreadGroup group, Runnable target, String name, long stackSize)

Runnable

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

一个对象实现Runnable接口来创建线程,启动这个线程导致在单独执行的线程中调用对象的run方法。

区别

实现多线程可以采用继承Thread类也可以采用实现Runnable接口,不过常用实现Runnable接口的方法,原因是:

  1. 可以避免单继承的局限性。Java中的继承,支持单继承、多重继承(A继承B,B继承C…..,N继承M),不支持多继承(C同时继承A和B)。当自己的类继承了Thread类,就无法去继承其他类。
  2. 增加程序的健壮性,实现解耦,降低耦合度,核心方法实现Runnable接口的类可以被多个线程共享,而且任务代码与线程独立,线程的任务代码和线程的启动代码分离。
  3. 线程池只能放入实现Runnable或Callable类的线程,自己写的继承自Thread的类无法放入线程池。实现Runnable涉及到资源共享的问题,而继承Tread的类资源相对独立。

Start&Run

Start 启动方法

/**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the 'run' method of this thread.
     * 
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the start method) 
     * and the other thread (which executes its run method).
     * 
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    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 */
            }
        }
    }
  • 使新线程开始执行,JVM调用该线程的start方法

  • 执行结果是两个线程同时执行
    1. 当前线程在调用新线程的start之后继续执行
    2. 新线程执行run方法
  • 每次启动线程是不合法的。特别是,线程一旦完成执行,就不能重复启动。

  • 主方法现场或系统组进程,无法调用start方法

  • threadStatus为0时,代表thread的状态为new

  • start0()是一个native方法。

    native方法:

    1. native与访问控制符前后关系不受限制
    2. native关键字必须在返回值之前
    3. native方法一般为非抽象方法
    4. native方法在异地实现

    native方法常作为java调用非java的接口:

    1. native方法是java方法
    2. native方法声明在java代码中
    3. native方法在异地用非java代码实现
    4. java在不同平台通过调用不同的native方法实现对操作系统的访问

Run 任务方法

/**
 * If this thread was constructed using a separate
 * Runnable run object, then that
 * Runnable object's run method is called;
 * otherwise, this method does nothing and returns.
 * 
 * Subclasses of Thread should override this method.
 *
 * @see     #start()
 * @see     #stop()
 * @see     #Thread(ThreadGroup, Runnable, String)
 */
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

区别

  1. start方法是启动一个线程,在新线程中执行run方法中的代码,结果是同时执行原线程和新线程
  2. run方法不会启动新线程,在同一线程中进行方法调用,结果是只有主线程
  3. Runnable作为Thread的target,Runnable中的run方法作为Thread的执行体。实际的线程对象是Thread实例,只不过Thread实例负责执行target的run方法。而线程的启动都要调用Thread实例的start方法。

Tips

  1. Thread.currentThread()是一个静态native方法,可以直接调用currentThread()返回一个Thread对象来获取当前线程,尤其是当没有当前线程的引用时,可以用这个方法对当前线程进行访问和设置。
  2. Thread的Priority默认为5,最小为1,最大为10,由Thread类中MIN_PRIORITY=1,NORM_PRIORITY=5,MAX_PRIORITY=10三个final static控制
  3. final关键字
    • final修饰的属性表明是一个常数
    • final修饰的方法表示在子类中不能被重写
    • final修饰的类表示不能被继承
    • final修饰的引用不可被修改,但引用的对象可以被修改
  4. static关键字
    • static与具体对象无关,强调只有一个
    • 不创建对象也能调用static修饰的属性和方法
  5. this&super
    • 与具体对象有关
  6. static final
    • 两关键字顺序没有影响,可以是static final,也可以是final static
    • static final表示值只有一个,而且是常量