突然发现和启动一个线程有关的有三函数,run()
, call()
, start()
,有点小乱,所以特别梳理一下
首先说一下start()
,这个是最好说的,感觉start()
和run()
这俩名字是真的有点容易混
其实,start()
是我们用extends Thread
方式写一个线程才会遇到的问题,其中的逻辑就是,start()
会调用run()
方法,就run()
方法自己而言,其实就是一个同步的方法,所以如果在main中直接调用一个线程的run方法,会看到多个线程会顺序执行。
只有用start方法开始线程,才能真正异步执行
上面只是简单提一下,下面说这篇文章的重点内容
Runnable 和 Callable 有什么区别呢
其实看一下run()
和 call()
的接口就知道了
public void run();
public Object call() throws Exception;
一个有返回值,一个没有。然而没这么简单,当我们要用他的返回值的时候,问题就出现了。
在说返回值之前,先简单说一下Callable
实现的线程怎么启动
Callable tt2 = new t2();
FutureTask task = new FutureTask<Integer>(tt2);
new Thread(task).start();
其中FutureTask
就是返回值的类型,这里是如何启动Callable
线程,还有其他的线程池方法,会在今后介绍线程池的时候讲解
下面就要说会发生什么问题了,其实就是我们可以通过get方法来获得线程的返回值,但是,在我们调用get的时候,如果线程尚未返回,那么调用者线程将会被阻塞,直到获取返回值
Callable tt2 = new t2();
FutureTask task = new FutureTask<Integer>(tt2);
task.get()
new Thread(task).start();
上面就是一个简单的死锁的例子,相信聪明的你一定理解我的意思了
个人的理解是Callable
线程更多地被应用在并行结算等场合上,而不是处理业务逻辑上,所以Callable
线程往往应该更短一些,同时可以一次启动多个,以便快速地获得相应的返回值