线程的定义:“线程是一种轻量级的进程,是由进程派生出来的子任务,它是程序执行的一个路径;每个线程都有自己的局部变量表、程序计数器(指向真正执行的指令指针)以及各自的生命周期”
start() && run()
要搞清楚这个问题,需要我们明确“线程的执行单元”与“线程”是两个不同的概念。在JAVA中通过Thread类重写的run()方法是线程的执行单元,而通过调用start()方法才是真正启动了一个线程,start()方法会使得该线程开始执行,java虚拟机会去调用该线程的run()方法
根据java api,Runnable接口只有一个方法,就是run(),start()方法是Thread的类方法
在不少关于JAVA线程的软文或者书籍中,经常会提到,创建线程有两种方式:
第一种是构造一个Thread
第二种是实现Runnable接口。
通过上面的分析,这种说法其实是不严谨的。在JDK中代表线程的只有Thread类,而Runnable接口只是简单定义了一个无参数返回值的run方法。而我们知道run方法只是定义了线程的执行单元,而并非直接开启了线程资源,只有Thread方法的start()方法才可以启动一个线程。
所以,如果面试中有人问你在JAVA中实现线程的方式有哪些?应该告诉他准确答案:“在JAVA中创建线程只有一种方式,那就是构造Thread类。而实现线程的执行单元则有两种方式,第一种是重写Thread类的run方法;第二种是实现Runnable接口的run方法,并且将Runnable实例用作构造Thread的参数”
Runnable && Callable
相同点:
两者都是接口;(废话)
两者都可用来编写多线程程序;
两者都需要调用Thread.start()启动线程;
不同点:
两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;
注意点:
Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞
网友评论