共计 2790 个字符,预计需要花费 7 分钟才能阅读完成。
来源概述
刚刚在准备面试刷题。于是想起好像有一个关于“Java 现成实现的方式”,于是百度(虽然盛传 * 度已死)、谷歌。然后结果。。。
[站外图片上传中 …(image-10f8bf-1569247170008)]
这坑不能忍啊!回答还能不能再给力一些。
这要是笔试或者面试有这个问题的话,那估计多少个面试机会都会死得不能再死了,还不知道到底根本原因是啥!!!这就相当可怕了。
于是找到官方 java tutorials 找结果:
意思就是实现线程只有两种方式
实现方式
第一种 实现 Runnalble 接口
Provide a Runnable object. The Runnable interface defines a single method, run, meant to contain the code executed in the thread. The Runnable object is passed to the Thread constructor, as in the HelloRunnable example:
public class HelloRunnable implements Runnable {public void run() {System.out.println("Hello from a thread!");
}
public static void main(String args[]) {(new Thread(new HelloRunnable())).start();}
}
第二种 继承 Thread 类
Subclass Thread. The Thread class itself implements Runnable, though its run method does nothing. An application can subclass Thread, providing its own implementation of run, as in the HelloThread example:
public class HelloThread extends Thread {public void run() {System.out.println("Hello from a thread!");
}
public static void main(String args[]) {(new HelloThread()).start();}
}
小提示
Notice that both examples invoke Thread.start in order to start the new thread.
- 启动用线程对象的 start 方法调用,正如上面两个示例程序一样。
- 实现代码都是写在 run 方法里面,或者被 run 方法直接或间接调用。
疑问
- Thread 方法也是通过实现 Runnable 接口来实现的,是不是可以归结为一种呢?
官方两种,至于程序员自己嘛 哼哼哼 都懂都懂哈!!!
- 带返回值的线程实现方式(FutureTask + 实现 Callable 接口)、基于线程池的方式(Executors.new.*ThreadPool)、内部类实现方式不算么?
答: 这些都是拓展了上面两种的的其中一种,内部类是那那种方式,其它如:
- 带返回值的线程实现方式(FutureTask + 实现 Callable 接口)
FutureTask 实现了 Runnable 接口,其中就包括了调用接口 Callable 接口的 call 方法,所以是可以通过实现 Callable 就可以实现线程,那还是第一种线程实现方式。FutureTask 部分代码如下:
public class FutureTask<V> implements RunnableFuture<V> {
// 重写了 run 方法 只是内部实现
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable; // 使用到 Callable
if (c != null && state == NEW) {
V result;
boolean ran;
try {result = c.call(); // 运行 call 方法
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result); // 设置返回值
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
}
- 基于线程池的方式(Executors.new.*ThreadPool)
其中 Executors.new.*ThreadPool 都是通过新建 ThreadPoolExecutor 类来实现的,而表示为工作任务的队列,所以这种也是第一种线程实现方式。Executors 部分代码如下:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {// 工作线程队列 实现 Runnable 接口
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
总结
网上的坑还是有,一不小心就掉进去了。像这个显而易见的线程实现问题还是很容易知道有问题的,找出正解也没什么太大难度。但是想想我们平常遇到的问题是那么“层出不穷”?网上搜索到的解决方案又是如此“百花齐放”(管你对不对)。所以凡是问题都不要留心眼,根本不够用。
- 学习资料,尽量从官方文档中学习,经典教材中学习;
- 解决问题,多方搜索,各种推敲,免不了各种查源码;
—- 致困扰本帅多年的简单线程实现方式问题