JAVA多线程03-基础篇-线程运行

本节摘要:分析Thread类的几个核心方法,对比start()和run()方法的区别

一、 源码解析

1.1、构造函数

public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc);
}
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}

1.2 参数说明

target:一个Runnable对象,线程启动后,会调用它的run()方法
name:线程名字
group:线程所属分组,如果没有指定,线程被归入到该线程的父线程的线程组中
stackSize:线程堆栈大小
AccessControlContext :设置访问权限控制环境

1.3 常用方法

public void start();//启动一个新线程,该方法将立即返回,新线程将运行
public void run();//覆盖该方法,添加线程具体执行内容
public static void sleep(long millis) throws InterruptedException;//使当前正在执行的线程睡眠指定的时间
public void interrupt();//用于将一个中断请求发送给线程
public static boolean interrupted();//用于测试当前线程(即正在执行该指令的线程)是否已经被中断
public boolean isInterrupted();//用于测试某个线程是否已经被中断
public final boolean isAlive();//用于测试某个线程是否还活着
public final void setPriority(int newPriority);//设置线程的优先级

1.4 关键方法分析

  • init()方法:Thread构造器都会调用init()方法,它的作用是初始化一个Thread,接下来我们看看init方法具体做了什么
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
    //线程名字不能为空,否则抛NPE
    if (name == null) {
      throw new NullPointerException("name cannot be null");
    }
    this.name = name;
    //获得父线程,即当前线程,此时新的线程还没有被创建,currentThread()是本地方法
    Thread parent = currentThread();
    //获取系统的安全管理器,安全管理器是一个允许应用程序实现安全策略的类
    SecurityManager security = System.getSecurityManager();
    //线程组为空
    if (g == null) {
    /* If there is a security manager, ask the security manager  what to do. */
    if (security != null) {
      g = security.getThreadGroup();
    }

    //如果没有指定线程组,则获取父线程的线程组
    if (g == null) {
      g = parent.getThreadGroup();
    }
}

/* checkAccess regardless of whether or not threadgroup is explicitly passed in. */
    g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
    if (isCCLOverridden(getClass())) {
        security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
    }
}
//将线程组中就绪的线程数加1
g.addUnstarted();

this.group = g;
this.daemon = parent.isDaemon();//根据父线程是否为守护线程来设置线程实例是否为守护线程
this.priority = parent.getPriority();//获取父线程的线程优先级
//设置classLoader
if (security == null || isCCLOverridden(parent.getClass()))
      this.contextClassLoader = parent.getContextClassLoader();
else
      this.contextClassLoader = parent.contextClassLoader;
//设置访问控制权限
this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();
this.target = target;//线程实例,就是构造器传进来的Runnable,线程执行就是执行该实例的run方法
setPriority(priority);//设置线程优先级
//将父线程的ThreadLocaleMap变量信息拷贝到当前线程实例
if (parent.inheritableThreadLocals != null)
      this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
      /* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;//线程堆栈大小

/* Set thread ID */
tid = nextThreadID();//线程ID
}
  • start()方法:线程调用start方法,就进入到Runnable状态,看看start()里都做了什么
//这是一个同步方法
public synchronized void start() {
    //状态为0代表状态为new,只有状态为new的线程才能调用start(),下面的逻辑表明start方法只能被执行一次
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    group.add(this);
    boolean started = false;
    try {
          start0();//启动线程,是一个本地方法,c语言实现
          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 */
                    }
          }
}
  • run方法
@Override
public void run() {
      //target是一个Runnable的实例,新创建的线程实际运行这个Runnable实例的run方法,因此需要重写该方法
      if (target != null) {
          target.run();
      }
}

二、示例

public class MyThread extends Thread {
  public static void main(String[] args) {
      // System.out.println("主线程名字:" + Thread.currentThread().getName());
      // System.out.println(Thread.currentThread().getThreadGroup().getName());
    Thread thread = new MyThread("myThread");
    thread.run();//直接调用run方法
    thread.start();//新启动一个线程
}

public MyThread(String name) {
    super(name);
}
@Override
public void run() {
      System.out.println("线程名字:" + Thread.currentThread().getName());
      // System.out.println(Thread.currentThread().getThreadGroup().getName());
      try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
        e.printStackTrace();
           }
      }
}
输出结果:
线程名字:main
线程名字:myThread

三、总结

程序从main方法开始,首先创建了一个线程实例,然后直接调用run方法,此时并没有开启新的线程,而是在"主线程"中直接运行的run方法,因此线程名是main,紧接着程序调用start()方法,jvm开启一个新的线程,并执行新线程的run方法,此时线程名为"myThread"。
因此:
start():启动一个线程,新线程会执行run()方法
run(): 和普通方法没有区别,如果单独调用run()方法,会在当前线程执行run方法**

转载请注明作者及出处,并附上链接http://www.jianshu.com/u/ada8c4ee308b

你可能感兴趣的:(JAVA多线程03-基础篇-线程运行)