1、继承Thread类,重写run方法:
弊端是:该类如果有继承其他类,那么则不能继承Thread,因为java不能多继承。如果采用继承的方式每次新建一个线程时,每个新建线程的数据都会单独的存在线程内存中,这样每个线程会单独的操作自己线程的数据,不能更好的实现线程之间的数据共享
调用的时候是new Demo类,然后调用start()
结果:
2、实现Runnable接口,重写run方法.
调用的时候是和继承Thread类有点区别,是
Thread t = new Thread(实现Runnable接口的那个类的对象);
t.start();
结果:
废话说完了,上面两种方式的缺点是:线程执行完就完了,无法获取到线程的执行结果,很多情况下是要开启多线程去计算,然后要获取结果的,因为重写run方法的返回值是void。但是代码可以这样写:使用lambda的形式
这样就可以获取到线程的执行结果了
但是这样代码不容易维护,而且有时候使用不好还容易出现线程安全问题。
实现Callable重写call方法
实现Callable和实现Runnable类似,但是功能更强大,具体表现在
1、可以在任务结束后提供一个返回值,Runnable不行
2、call方法可以抛出异常,Runnable的run方法不行
3、可以通过运行Callable得到的Future对象监听目标线程调用call方法的结果,得到返回值,(future.get(),调用后会阻塞,直到获取到返回值)
使用Callable接口实现多线程的步骤
乍一看这个代码很难记。其实这样看。
首先看Thread thread = new Thread ( futureTask),那就说明 futureTask是一个Runnable。因为实现了Runable接口的话,Thread才可以这样传参数:
所以可知,FutureTask实现了Runnable接口
FutureTask等于实现了Runnable和Future接口。所以具备Future的get方法,获取值
FutureTask的参数是Callable或者是Runnable
要想运行Thread的参数是Runnable,而FutureTask刚好是Runnable接口的实现类,所以Thread的参数是FutureTask,而FutureTask的参数是callable或者Runnable。
new Thread(new FutureTask(new Callable))。
以上就是Callable接口该如何运行,以及如何得到线程的运行结果。
另一方面,还可以通过线程池来提交:
线程池提交的任务的时候,提交的肯定是线程啊,所以提交的参数是Callable和Runnable,一个是提交了可以获取到执行结果的,另一个是提交了纯属是去执行,不用得到结果。返回值都是Future。假如提交的是callable,那么可以用Future的get方法获取callable的执行结果
FutureTask和Future的关系,
因为实现了Future接口,所以才可以.get()获取到线程的执行结果,
get方法是Future接口里的。
总结:
在Tread中有一个构造方法是传入一个Runnable接口类型的参数,而FutureTask<V>实例实现了 RunnableFuture<V> 接口,而 RunnableFuture<V> 接口又继承了Runnable接口和 Funture<V>接口,因此可以把FutureTask<V> 的一个实例当做是一个Runnable接口的实例传入Thread来启动新建的线程
get方法是会阻塞的
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
添加我为好友,拉您入交流群!
请使用微信扫一扫!