刚刚在准备面试刷题。于是想起好像有一个关于“Java县城实现的方式”,于是百度(虽然盛传*度已死)、谷歌。然后结果。。。
[站外图片上传中...(image-10f8bf-1569247170008)]
这坑不能忍啊!回答还能不能再给力一些。
这要是笔试或者面试有这个问题的话,那估计多少个面试机会都会死得不能再死了,还不知道到底根本原因是啥!!! 这就相当可怕了。
于是找到官方 java tutorials 找结果:
意思就是实现线程只有两种方式
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(); } }
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.
官方两种,至于程序员自己嘛 哼哼哼 都懂都懂哈!!!
答:这些都是拓展了上面两种的的其中一种,内部类是那那种方式,其它如:
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 都是通过新建 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); }
网上的坑还是有,一不小心就掉进去了。像这个显而易见的线程实现问题还是很容易知道有问题的,找出正解也没什么太大难度。但是想想我们平常遇到的问题是那么“层出不穷”?网上搜索到的解决方案又是如此“百花齐放”(管你对不对)。所以凡是问题都不要留心眼,根本不够用。
----致困扰本帅多年的简单线程实现方式问题