最近对Core Java基础做了一些学习。有自己的见解,也有别人的总结,供大家参考。

1 实现多线程的方式有几种?

其实这个问题并不难,只是在这里做一个总结。一共有三种。

  • 实现Runnable接口,并实现该接口的run()方法
  • 继承Thread类,重写run()方法
  • 实现Callable接口,实现call()方法。

大家可能对前两种已经很清楚了,重点说下第三种。
Callable接口是属于Executor框架中的类,Callable 接口与Runnable接口类似,但比后者功能更加强大,主要有三点:

  1. Callable可以在任务结束后提供一个返回值,Runnable无法提供这个功能;
  2. Callablecall()方法可以抛出异常,Runnable接口的run()方法不能抛出异常;
  3. 运行Callable可以得到一个Future对象,Future对象表示异步计算的结果。它提供了检查计算是否完成的方法。由于线程属于异步计算模型,所以无法从其他线程中得到方法的返回值。在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况。当调用Futrueget()方法以获取结果时,当前线程就会阻塞,直到call()方法结束返回结果。

举个例子,此代码在JDK 8 下运行,因为使用了lambda表达式:

package exam;import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class CallableAndFuture {public static void main(String[] args) {ExecutorService threadPool = Executors.newSingleThreadExecutor();// 启动线程Future<String> future = threadPool.submit(() -> "Hello, world");try {System.out.println("waiting thread to finish.");System.out.println(future.get()); // 等待线程结束,并获取返回结果threadPool.shutdown();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}
}

2 volatile关键字的作用

在Java语言中,有时候为了提高程序的运行效率,编译器会做一些优化操作,把经常被访问的变量缓存起来,程序在读取这个变量的时候又有可能直接从寄存器中读取这个值,而不会去内存中读取。这样的好处提高了程序的运行效率,但当遇到多线程编程时,变量的值可能被其他线程改变了,而该缓存的值不会做相应的改变,从而导致应用程序读取的值可能与实际的变量值不一致。关键字volatile正好解决这个问题,被volatile修饰的变量编译器不会做优化,每次都会从内存读取。

3 代码中不同属性和方法的执行顺序

经常会遇到一个这样的代码,new一个子类,其子类以及父类每个属性和方法的执行顺序,具体可以看以下例子:

*** Java程序初始化工作可以在许多不同的代码中来完成,它们执行的顺序如下:* 父类静态变量* 父类静态代码块* 子类静态变量* 子类静态代码块* 父类非静态变量* 父类非静态代码块* 父类构造函数* 子类非静态变量* 子类非静态代码块* 子类构造函数* * * 注意,只有方法具有多态性,属性则没有。* @author TurtusLi**/
class BaseI {int num = 1;public BaseI() {this.print();num = 2;}public void print() {System.out.println("Base.num = " + num);}
}public class Example1423 extends BaseI {int num = 3;public Example1423() {this.print();num = 4;}// 去掉这个复写方法,运行看效果@Overridepublic void print() {System.out.println("Sub.num = " + num);}public static void main(String[] args) {BaseI b = new Example1423();System.out.println(b.num);}}

4 switch语句支持String类型的实现原理

在Java 7 以后,switch语句可以用作String类型上。

从本质来讲,switch对字符串的支持,其实也是int类型值的匹配。它的实现原理如下:

通过对case后面的String对象调用hashCode()方法,得到一个int类型的Hash值,然后用这个Hash值来唯一标识着这个case

那么当匹配的时候,首先调用这个字符串的hashCode()方法,获取一个Hash值(int类型),用这个Hash值来匹配所有的case,如果没有匹配成功,说明不存在;如果匹配成功了,接着会调用字符串的equals()方法进行匹配。

由此看出,String变量不能是null;同时,switchcase子句中使用的字符串也不能为null。

5 多线程同步有几种实现方法

Java主要提供了三种实现同步机制的方法。

  1. synchronized关键字。有两种用法,可以是synchronized方法和synchronized代码块。
  2. waitnotify方法。
  3. LockLock接口有一个实现类ReentrantLock,也可以实现多线程的同步。

6 在多线程编程的时候有哪些注意事项

  1. 如果能用volatile代替synchronized,近可能使用volatile。因为被synchronized修饰的方法或代码块在同一时间只能允许一个线程访问,而volatile没有这个限制,因此使用synchronized会降低并发量。由于volatile无法保证原子性操作,因此在多线程的情况下,只有对变量的操作为原子操作的情况下才可以使用volatile
  2. 尽可能减少synchronized块内的代码。
  3. 给每一个线程定义一个名字,这样有利于调试。
  4. 尽量使用concurrent容器(ConcurrentHashMap)来代替synchronized容器(Hashtable)。
  5. 使用线程池来控制多线程的执行。

7 fail-fast 和fail-safe迭代器的区别是什么?

他们的主要区别是fail-safe允许在遍历的过程中对容器的数据进行修改,而fail-fast则不允许。下面分别介绍这两种迭代器的工作原理。

fail-fast:直接在容器上进行遍历,在遍历的过程中,一旦发现容器中的数据被修改了(添加元素、删除或修改元素),就会抛出ConcurrentModificationException异常导致遍历失败。常见的使用fail-fast的容器有HashMapArrayList等。

fail-safe:这种遍历是基于容器的克隆。因此,对容器中内容的修改不影响遍历。常见使用fail-safe方式的容器有ConcurrentHashMapCopyOnWriteArrayList

8 如何能够使JVM中的虚拟机栈、堆内存和方法区发生内存溢出?

关于JVM的知识,有一本非常好的书籍——周志明《深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)》,里面有非常好的介绍。几乎可以说是Java程序员必读书籍。

虚拟机栈是线程私有的,当创建一个线程时,同时会新建一个虚拟机栈,它描述的是Java方法执行的内存模型。 栈中有一个非常重要的概念——栈帧。栈帧用于保存局部变量表,操作数栈,方法出口等。

其实栈溢出最简单的方式是无限递归。

堆内存是线程共享的,是JVM中内存管理的最大一块内存,它保存所有实例化的对象。

堆内存溢出最简单的方式是不停的new对象,GC来不及回收,直到内存全部耗尽。

方法区也是内存共享的。它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

方法区溢出简单的方式是,调用String类的intern()方法,此方法如果在堆区找不到已经存在的String对象的话,就会往方法区中的常量池放一份,然后返回其引用放在堆区。还有一种办法是不停地加载类。

9 在 int i =0; i=i++;语句中,i=i++是线程安全的吗?如果不安全,请说明上面操作在JVM中的执行过程,为什么不安全?说出JDK中哪个类能达到以上程序的效果,并且是线程安全且高效的,简述其原理。

语句i=i++的执行过程:先把i的值取出来放到栈顶,可以理解为引入了第三方变量k,此时,k的值为i,然后执行自增操作,于是i的值变为1,最后执行赋值操作i=k(自增前的值),因此,执行结束后,i的值还是0。从上面的分析得知,i=i++语句的执行过程是由多个操作组成,它不是原子操作,因此,不是线程安全的。

在Java中,++ii++操作并不是线程安全的,在使用的时候,不可避免地会用到synchronized关键字。而AtomicInteger是一个提供原子操作的Integer类,它提供了线程安全且高效的原子操作,是线程安全的,其底层的原理是利用处理器的CAS(Compare And Swap,比较与交换,一种有名的无锁算法)操作来检测栈中的值是否被其他线程改变,如果被改变,则CAS操作失败。这种实现方法在CPU指令级别实现了原子操作,因此,它比使用synchronized来实现同步效率更高。

Java 学习内容总结相关推荐

  1. JAVA学习内容汇总(一)

    一.JAVA的历史 在JAVA学习前,我们粗略了解JAVA的由来,以前编写程序非常麻烦,而且安全性没有很高,Sun公司用一种全新的语言编写了一个浏览器,该组成员在一家名为"爪哇"的 ...

  2. Java学习内容之需要辨识的英文单词(持续更新)

    单词: variable变量 resolve辨识 symbol标识 assign赋值 expression表达式 exception异常 initialization初始化n initialize初始 ...

  3. 【日记】Java学习日记(第63天)持续无聊更新

    前言 Youtube上EJ Media(up主)的视频我依次学完了HTML.CSS.Javascript.Jquery.觉得他教得挺好的(短小精悍),就继续学他教的JAVA.感觉EJ教的都是些语法什么 ...

  4. Java技术依然备受追捧,主要学习内容有哪些?

    Java技术依然备受追捧,主要学习内容有哪些?Java 语言是一门随时代快速发展的计算机语言程序,其深刻展示了程序编写的精髓,加上其简明严谨的结构及简洁的语法编写为其将来的发展及维护提供了保障. 在众 ...

  5. 【JavaScript总结】JavaScript发展与学习内容

    发展: 最初浏览器是为大学里浏览文档用,从地址栏输入文档地址,找到文档显示. 后来各种需求(购物网站,个人博客)出现,已有功能不能满足需求. 可人们依旧在努力满足这种需求,但实现后的效果很不尽人意. ...

  6. Java学习路线图,如何学习Java事半功倍?

    作为一个初学者想掌握Java并不是很容易,Java本身是具有一定难度的,虽然说兴趣这东西可以让我们学习不累,但是有多少人学习是因为兴趣,或者有多少人知道自己的兴趣在哪?所以我很明确的告诉你学习这事本来 ...

  7. java学习笔记11--Annotation

    java学习笔记11--Annotation Annotation:在JDK1.5之后增加的一个新特性,这种特性被称为元数据特性,在JDK1.5之后称为注释,即:使用注释的方式加入一些程序的信息. j ...

  8. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

  9. 我的WEB之路(一)-2.JAVA学习路线

    第一阶段:针对性夯实JAVA基础 课程名称 核心要点 完成目标 Java基础入门 搭建Java开发和运行环境等,IDE工具的学习和使用,Java语言基础,数据类型,运算符,条件和循环,数组使用等,Ja ...

最新文章

  1. StaticLayout的介绍/使用
  2. 高德地图API 简单使用
  3. 敏捷开发_全面解析瀑布式开发和敏捷式开发
  4. python第三方插件登录网易音乐_python3-使用requests模拟登录网易云音乐
  5. 推荐一款生成SQL插入语句的软件
  6. [正则表达式] 正则表达式匹配UUID
  7. 以links方式安装eclipse插件
  8. mysql_store_result和mysql_use_result
  9. GdiPlus使用方法
  10. linux智能系统下载软件,NI Linux RT System Image 20.5 NI Linux实时系统映像2020.09
  11. 安装VMware tools好处
  12. oliver什么意思java_英语名字“oliver”是什么意思?
  13. 门萨--高智商者的集中营
  14. 微擎弹出确认授权获取用户头像
  15. 创业者该怎么快准狠抓住知识付费项目这个机会变现?
  16. 【机器学习】——梯度下降法的收敛性证明(详解)
  17. C#按Excel 规则读取、写入CSV文件,放入DataTable,再读取、写入dataGridView内。包含解析转义字符,首行判断,转换完成信号等。
  18. Compact set,紧集,闭集,开集
  19. 怀揣坚定与执着,踏实稳步向前
  20. 嵌入式openwrt平台(mt7688)上使用讯飞语音服务

热门文章

  1. linux下wc命令详解
  2. 常用控件产品官方文档/手册/API列表 c#控件文档API列表 asp.net控件产品技术文档中文版...
  3. 帝国cms底部代码哪里改?要修改版权和统计代码
  4. Linux中find常见用法示例
  5. 2009全国公共英语五级(PETS-5)考试大纲概述
  6. 如何使用 CODING 实践 DevOps 全流程
  7. 从分治算法到 MapReduce
  8. eclipse中Tomcat启动了 但看不到tomcat首页
  9. 在spring MVC项目中集成Spring session redis (使用spring session框架,redis作为存储缓存)...
  10. 06-老马jQuery教程-jQuery高级