学习java8API笔记开篇-并发
用java语言撰写程序已经多年,时不时问问自己,真的了解jdk的api的设计原理,而不是靠的死记硬背学会使用,然而身边大多数程序员会告诉我,会用就可以,是事实不是这样的,去年我面试阿里失败后,我就在反思我的学习方式,现在做一些调正,提高要求,不仅要会用,还要看懂源码,学习设计api的思想。
从下图看,整个java的生态很大,想要每个了解到位是不可能的,先从java语言的api中的java.util.concurrent包中并发编程开始。
在面试时,你会发现不同的人对并发有着不一样的理解和看法,正确的理解并发摘取了网上的一句解释很到位的:计算机用户理所当然地认为他们的系统一次可以做多件事。他们假设他们可以继续在文字处理器中工作,而其他应用程序则下载文件,管理打印队列和流音频。即使是单个应用程序通常也希望一次完成多个任务。而可以执行这样操作的软件我们叫它并发软件。所以在5.0以后java就支持了并发执行任务。
线程对象
每个线程都与该类的实例相关联 Thread
。使用Thread
对象创建并发应用程序有两种基本策略。
- 要直接控制线程创建和管理,只需
Thread
在应用程序每次启动异步任务时进行实例化。 - 要从应用程序的其余部分抽象线程管理,请将应用程序的任务传递给执行程序。
创建和定义线程
创建实例的应用程序Thread
必须提供将在该线程中运行的代码。有两种方法可以做到这一点:
提供一个Runnable
对象。该 Runnable
接口定义了一个方法,run
,意在包含在线程执行的代码。该Runnable
对象被传递给Thread
构造函数,如:
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
。在Thread
类本身实现了Runnable
,虽然它的run
方法不起作用。应用程序可以子类化Thread
,提供自己的实现run
,如
public class HelloThread extends Thread { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new HelloThread()).start(); } }
请注意,两个示例都会调用Thread.start
以启动新线程。我们应该使用哪一个?
第一个使用Runnable
对象的习语更为通用,因为该Runnable
对象可以继承一个类以外的类Thread
。第二个习语在简单的应用程序中更容易使用,但受到任务类必须是后代的限制Thread
。本Thread
类定义了大量的线程管理有用的方法。这些static
方法包括提供有关调用方法的线程的信息或影响其状态的方法。
————————————————————————–面试题和总结————————————————————–
面试题分享:有几种方式创建线程,每种方式有什么不同,各有什么优劣?
这是经常问到的面试题,旨在考查对多线程编程了解的程度,很多也是从网上直接下载下来的题目,在企业里很少使用到多线程编程,都在写业务代码,但是这样一问就知道你在上架公司担任什么水准的职位,什么职位就会去考虑什么问题,我们想更好的发展就必须知道其使用的场景和基本原理,以备工作和面试的需要。
Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用三种方式来创建线程,如下所示:
1)继承Thread类创建线程
2)实现Runnable接口创建线程
3)使用Callable和Future创建线程
回答出①和②已经可以算是初步了解些,能够说出第三种与前两种区别的人初级和中级和很少,所以认真对待这道面试题。
接口Future
表示异步计算的结果。提供方法以检查计算是否完成,等待其完成,以及检索计算结果。
interface ArchiveSearcher { String search(String target); } class App { ExecutorService executor = ... ArchiveSearcher searcher = ... void showSearch(final String target) throws InterruptedException { Future<String> future = executor.submit(new Callable<String>() { public String call() { return searcher.search(target); }}); displayOtherThings(); // do other things while searching try { displayText(future.get()); // use future } catch (ExecutionException ex) { cleanup(); return; } } }
FutureTask
类是的一个实现Future
一个实现Runnable
,所以可以通过执行Executor
。例如,上述结构submit
可以替换为:
FutureTask<String> future = new FutureTask<String>(new Callable<String>() { public String call() { return searcher.search(target); }}); executor.execute(future);
接口Callable <V>
这是一个功能接口,因此可以用作lambda表达式或方法引用的赋值目标。
call()
计算结果,如果无法执行,则抛出异常。
|