【多线程】开启多线程的启动世界

启动线程正确和错误的方式

1.start()run()的比较

//调用run方法
Runnable runnable = () -> {
	System.out.println("thread name is " + Thread.currentThread().getName() + ",thread id="  + Thread.currentThread().getId());
};

runnable.run();

//调用start方法
Thread thread = new Thread(runnable);
thread.start();

输出结果:

thread name is main,thread id=1
thread name is Thread-0,thread id=12

结论:从输出结果可知run()方法并不能启动一个线程,执行该方法的还是主线程。

2.start()方法原理解读

  • 方法含义
  • 启动新线程

线程对象在初始化之后,调用start方法,于是当前线程(主线程)执行start方法,并通知虚拟机执行新线程。start方法的作用是通知JVM在有空闲的情况下启动新线程。子线程何时执行是由线程调度器控制的,start方法调用结束之后并不意味着线程能已经在运行了。调用start方法的顺序并不能决定执行线程的顺序。start方法会让两个线程启动一个是主线程(或者是执行子线程的线程),另一个是子线程。

  • 准备工作

新建的线程处于就绪状态(已经获取到除了CPU以外的其它资源)

  • 不能重复两次执行start方法。
public static void main(String[] args) {
	Runnable runnable = ()->{
		System.out.println("thread name is " + Thread.currentThread().getName() + ",thread id="  + Thread.currentThread().getId());
	};
	Thread thread = new Thread(runnable);
	thread.start();
	thread.start();
}

输出结果

Exception in thread "main" java.lang.IllegalThreadStateException
   at java.lang.Thread.start(Thread.java:708)
   at com.whaleson.threadcoreknowledge.startthread.CantStartTwice.main(CantStartTwice.java:19)

解析:线程一旦开始执行就从最开始的new状态进入到后续的状态。一旦线程执行完毕,线程就会变成终止状态,而终止状态永远不可能返回回去。

  • 源码解析
    • 启动新线程检查线程状态
    • 加入线程组
    • 调用start0()
  • 深入JDK源码
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 */
		}
	}
}

3.run()方法原理解读

  • 源码解析
  • 两种情况
    • 重写Thread类的run方法
    • 实现Runnable接口的run方法
public void run() {
    if (target != null) {
        target.run();
    }
}

4.常见面试问题

  • 一个线程两次调用start()方法会出现什么情况?为什么?
  • 既然start()方法会调用run()方法,为什么我们选择调用start()方法,而不是直接调用run()方法呢?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值