锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Java基础部分

时间:2023-02-05 09:00:00 0804zb4m圆形电连接器

一些基本部分的总结,基本上是在学习中遇到的一些问题,有些来自其他博客,有些来自他们自己的总结,如果有侵权行为,请联系我并道歉。

---------------------------------------------------------------------------------------------------------------------
java注释中代码和快捷键

添加必要的注释,对于一个负责任、道德模范的前端必须有良好的习惯,

可大大提高代码的可维护性和可读性。

java代码注释快捷键:文本注释ctrl shift /
单行注释ctrl /
多行注释ctrl shift c
文档注释alt shift j
先熟悉一下html、css、js注释写法:
1、HTML注释语法:



2、css注释语法

/* 注释内容 */
/* ----------文字风格开始---------- */

3、javaScript注释

//注释内容
/*注释内容*/

下一步是总结注释在这些代码中使用的位置,以及如何写注释。惯可能不同)
1、html注释
使用的位置:
一般在一些主要节点标签结束后使用,如:

...


2)在一些循环结束后使用,如:

  • 111111
  • 222222
  • 333333




2、css注释
它通常用于定义模块样式,表示该样式作用于哪个模块,如:

/*通用 - 评论*/ .comment{...} /*相册*/ .photo{...} /*分享*/ .share{...} /*投票*/ .vote{...}

3、javascript注释
注释通常添加到某个功能函数中,表示函数的功能、作者、作者信息和修改时间。

//======================================================== // 截断字符 // steepvi // rtx:******* // 2010-10-14 //========================================================

最后,注释也是字符也会产生流量。因此,当页面发布到正式地址时,最好添加一步优化流程。
ctrl /

ctrl shift c

以下是myeclipse所有快捷键列表:
Ctrl 1 快速修复(不用说最经典的快捷键)
Ctrl D: 删除当前行
Ctrl Alt ↓ 复制到下一行(复制增加)
Ctrl Alt ↑ 复制到前一行(复制增加)
Alt ↓ 目前与以下一行的交互位置(特别实用,可以先剪后粘贴)
Alt ↑ 当前与上述交互位置(同上)
Alt ← 前一个编辑页面
Alt → 下一个编辑页面(当然是针对上面的)
Alt Enter 显示当前资源选择(工程,or 文件 or文件)属性
Shift Enter 将空行插入当前行的下一行(此时鼠标可以在当前行的任何位置,不一定是最后)
Shift Ctrl Enter 在当前行插入空行(原则与上条相同)
Ctrl Q 定位到最后编辑的地方
Ctrl L 定位在某行 (程序超过100的人有福音)
Ctrl M 最大化当前Edit或View (反之亦然)
Ctrl / 注释当前,然后取消注释
Ctrl O 快速显示 OutLine
Ctrl T 快速显示当前继承结构
Ctrl W 关闭当前Editer
Ctrl K 参照选中的Word快速定位到下一个
Ctrl E 快速显示当前Editer下拉列表(如果当前页面没有显示黑体)
Ctrl //(小键盘) 折叠当前类中的所有代码
Ctrl ×(小键盘) 在当前类中扩展所有代码
Ctrl Space 代码助手可以完成一些代码的插入(但通常与输入法有冲突,可以修改输入法的热键,也可以暂时使用Alt /来代替)
Ctrl Shift E 目前所有打开显示管理的显示管理View管理器(可选择关闭、激活等操作)
Ctrl J 搜索正增量(按下)Ctrl J之后,您输入的每个字母编辑器都为单词提供快速匹配定位。如果没有,那就是stutes line中显示器没有找到。检查单词时特别实用。这个功能Idea两年前就有了)
Ctrl Shift J 反向增量搜索(和上面一样,只是从后到前)
Ctrl Shift F4 关闭所有打开的Editer
Ctrl Shift X 把当前选中的文本全部变味小写
Ctrl Shift Y 将当前选定的文本全部变成小写
Ctrl Shift F 当前代码格式化
Ctrl Shift P 对匹配符(如{})的定位 (从前面定位后面时,光标应在匹配符中,后面到前面,反之亦然)

下面的快捷键是重建中常用的,我会整理出我喜欢和常用的快捷键(注:一般重建的快捷键都是Alt Shift开头的了)
Alt Shift R 重命名 (是我最喜欢的,尤其是变量和类别Rename,比手工方法节省大量劳动力)
Alt Shift M 抽取方法 (这是重构中最常用的方法之一,尤其是对大量泥团代码有用)
Alt Shift C 修改函数结构(更实用,有N个函数调用此方法,修改一次)
Alt Shift L 提取本地变量( 一些魔法数字和字符串可以直接提取成一个变量,特别是个地方调用时)
Alt Shift F 把Class中的local变量变为field变量 (实用功能)
Alt Shift I 合并变量(可能有点不合适)Inline)
Alt Shift V 移动函数和变量(不怎么常用)
Alt Shift Z 重构后悔药(Undo)


查看
作用域 功能 快捷键
全局 放大 Ctrl =
全局 缩小 Ctrl -

窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl Shift W
全局 最后一个编辑器 Ctrl Shift F6
全局 上一个视图 Ctrl Shift F7
全局 最后一个透视图 Ctrl Shift F8
全局 下一个编辑器 Ctrl F6
全局 下一个视图 Ctrl F7
全局 下一个透视图 Ctrl F8
文本编辑器 显示标尺上下文菜单 Ctrl W
全局 显示视图菜单 Ctrl F10
全局 显示系统菜单 Alt -

文件
作用域 功能 快捷键
全局 保存 Ctrl X
Ctrl S
全局 打印 Ctrl P
全局 关闭 Ctrl F4
全局 全部保存 Ctrl Shift S
全局 全部关闭 Ctrl Shift F4
全局 属性 Alt Enter
全局 新建 Ctrl N

源代码
作用域 功能 快捷键
Java编辑器 格式化 Ctrl Shift F
Java编辑器 取消注释 Ctrl \
Java编辑器 注释 Ctrl /
Java编辑器 添加导入 Ctrl Shift M
Java编辑器 组织导入 Ctrl Shift O
Java编辑器 使用try/catch块来包围 不设置,太常用,所以在这里列出,建议自己设置。
也可以使用Ctrl 1自动修正。

运行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入选择 Ctrl F5
全局 上次开始调试 F11
全局 继续 F8
全局 单步使用过滤器 Shift F5
全局 添加/去除断点 Ctrl Shift B
全局 显示 Ctrl D
全局 最后一次操作 Ctrl F11
全局 运行至行 Ctrl R
全局 执行 Ctrl U

重构
作用域 功能 快捷键
全局 撤销重构 Alt Shift Z
全局 抽取方法 Alt Shift M
全局 抽取局部变量 Alt Shift L
全局 内联 Alt Shift I
全局 移动 Alt Shift V
全局 重命名 Alt Shift R
全局 重做 Alt Shift Y
/**
* @author sram
* @category 展示主方法
*/
public class MyTest {
///单行注释: 这种方法是主要方法Java代码的入口
public statc void main(String[] args) {
        /*
         * 主方法的方法体
         * 主方法的执行代码块为:System.out.println("HelloWorld");
         * 主要负责输出字符串"HelloWorld"
         */
        System.out.println("HelloWorld");
    }
}
-----------------------------------------------------------------------------------------------------------------------------------------
java用编译器编译成字节码,字节码用解释器运行,同一字节码可以在不同的操作系统下被不同的解释器运行,从而实现Java的跨平台性也就可移植性.

补充最重要的一点:因为字节码,即class文件是按规定标准排列的二进制文件,所以不同操作系统的java编译器都会编译出一致的字节码文件。
-----------------------------------------------------------------------------------------------------------------------------------------
ASCII码:一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。如一个ASCII码就是一个字节。
UTF-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。
Unicode编码:一个英文等于两个字节,一个中文(含繁体)等于两个字节。
符号:英文标点占一个字节,中文标点占两个字节。举例:英文句号“.”占1个字节的大小,中文句号“。”占2个字节的大小。

不同数量级间
数据存储是以10进制表示,数据传输是以2进制表示的,所以1KB不等于1000B。
1KB=1024B;1MB=1024KB=1024×1024B。其中1024=210。
1B(byte,字节)= 8 bit(见下文);
1KB(Kibibyte,千字节)=1024B= 2^10 B;
1MB(Mebibyte,兆字节,百万字节,简称“兆”)=1024KB= 2^20 B;
1GB(Gigabyte,吉字节,十亿字节,又称“千兆”)=1024MB= 2^30 B;
1TB(Terabyte,万亿字节,太字节)=1024GB= 2^40 B;
1PB(Petabyte,千万亿字节,拍字节)=1024TB= 2^50 B;
1EB(Exabyte,百亿亿字节,艾字节)=1024PB= 2^60 B;
1ZB(Zettabyte,十万亿亿字节,泽字节)= 1024EB= 2^70 B;
1YB(Yottabyte,一亿亿亿字节,尧字节)= 1024ZB= 2^80 B;
1BB(Brontobyte,一千亿亿亿字节)= 1024YB= 2^90 B;
1NB(NonaByte,一百万亿亿亿字节) = 1024 BB = 2^100 B;
1DB(DoggaByte,十亿亿亿亿字节) = 1024 NB = 2^110 B;[1]  

数据类型         储存空间大小(单位:字节)    范围
Byte(字节型)        1            0 - 255
Boolean(布尔型/逻辑型)    2            True 或 False
Integer(整数型)        2            -32,768 ~ 32767
Long(长整形)        4            -2,147,483,648 ~ 2,147,483,647
Single(单精度浮点型)    4            负数范围:-3.402823E38 ~ -1.401298E-45 正数范围:1.401298E-45 ~ 3.402823E38
Double(双精度浮点型)    8            负数范围:-1.797,693,134,862,32E308 ~-4.940,656,458,412,47E-324
                        正数范围:4.940,656,458,412,47E-324 ~1.797,693,134,862,32E308
Currency(变比整形 / 货币类型) 8            -922,337,203,685,477.5808 ~922,337,203,685,477.5807
Decimal(十进制型)    14            没有小数点时:+/-79,228,162,514,264,337,593,543,950,335
                        有小数点时:+/-7.922,816,251,426,433,759,354,395,033,5
                        最小的非零值:+/-0.000,000,000,000,000,000,000,000,000,1
Date(时间日期型)    8            100 年 1 月 1 日 ~ 9999 年 12 月 31 日
Object(对象型)        4            任何 Object 引用
String (变长)        10            长度从 0 到 大约 20 亿
String (定长)        10            长度从 1 到大约 65,400
Variant (数字)        16            任何数字值,最大可达 Double 的范围
Variant (字符)        22            与字符串长度,变长 String 有相同的范围


B与bit
数据存储是以“字节”(Byte)为单位,数据传输是以大多是以“位”(bit,又名“比特”)为单位,一个位就代表一个0或1(即二进制),每8个位(bit,简写为b)组成一个字节(Byte,简写为B),是最小一级的信息单位。
B与iB
1KB(Kibibyte)=1024byte
1KiB(Kilobyte)=1000byte
1MB(Mebibyte)=1048576byte
1MiB(Megabyte)=1000000byte
硬盘生产商是以GiB(十进制,即10的3次方=1000,如1MiB=1000KB)计算的,而电脑(操作系统)是以GB(2进制,即2的10次方, 如1MB=1024KB)计算的,但是国内用户一般理解为1MiB=1M=1024 KB, 所以为了便于中文化的理解,翻译MiB为MB也是可以的。
同样根据硬盘厂商与用户对于1MB大小的不同理解,所以好多160G的硬盘实际容量按计算机实际的1MB=1024KB算都不到160G,这也可以解释为什么新买的硬盘“缺斤短两”并没有它所标示的那么大。
注:10TB大约等于一个人脑的存储量。


字符人们使用的记号,抽象意义上的一个符号。 '1', '中', 'a', '$', '¥' ……
字节计算机中存储数据的单元,一个8位的二进制数,是一个很具体的存储空间。0x01, 0x45, 0xFA……
-----------------------------------------------------------------------------------------------------------------------------------------
单精度 与 双精度:
单精度和双精度数值类型最早出现在C语言中(比较通用的语言里面),在C语言中单精度类型称为浮点类型(Float),顾名思义是通过浮动小数点来实现数据的存储。这两个数据类型最早是为了科学计算而产生的,他能够给科学计算提供足够高的精度来存储对于精度要求比较高的数值。

通过解剖单精度数值的二进制存储格式,我们可以清楚看到,实际上单精度/双精度的存储,都要通过乘法和除法,其中必有舍入,如果恰好你的数值在除法中被舍入了,那么你赋的初值就很可能与你最终存储的值不完全相同,其中的微小差异,并不与单精度/双精度的设计目标相违背。???
当我们在数据库中或者VBA代码中使用一个单精度/双精度数值的时候,也许你从界面上看不到区别,但是在实际的存储中,这个差别却真真切切地就在那里,当你对其进行相等比较的时候,系统只是简单地作二进制的比较,界面上无法体现的微小差异,在二进制比较面前却无处遁形,于是,你的等于比较返回了一个意料之外的False。
(1)在内存中占有的字节数不同

?单精度浮点数在机内占4个字节

?双精度浮点数在机内占8个字节

(2)有效数字位数不同

?单精度浮点数有效数字8位

?双精度浮点数有效数字16位

(3)所能表示数的范围不同

?单精度浮点的表示范围:-3.40E+38 ~ +3.40E+38

?双精度浮点的表示范围:-1.79E+308 ~ +1.79E+308

(4)在程序中处理速度不同

一般来说,CPU处理单精度浮点数的速度比处理双精度浮点数快


单精度实数在内存中占32bit  有效数字为6~7位

双精度实数占内存单元为64bit  有效数字为15~16位

因为小数在计算机中存储的多数为近似值,虽然符点数的表示方法(IEEE754标准)可以使得四字节或八字节表示很大的数据,但是,由于有的小数不能完全转换成纯粹相等的二进制数,所以,计算机只能保存最接近的其值的二进制小数。
-----------------------------------------------------------------------------------------------------------------------------------------
  在Java语言中,提供了多种整型数据类型:byte、short、int、long。它们都是定义了一个整数,唯一的区别就是它们能够表示数据的范

围。

  能够表示数据的范围越大,占用的内存空间也就越大,因此,在程序设计中应该选择最合适的类型来定义整数。

  大家可以根据以下规律,记住它们所占的内存空间:

  1) int是最基本的,它占用32位(现代计算机不就是32位机嘛!); 4字节

  2) long,长的,也就是比int还长,它占用64位; 8字节

  3) short,短的,也就是比short还短,它占用16位; 2字节

  4) byte,字节,8位组成一个字节,当然byte就只占8位了。 1字节

  根据它们所占用的内存空间不同,能够表示的数字范围也不同。占用内存空间越大,能够表示的数字范围也就越广。
-----------------------------------------------------------------------------------------------------------------------------------------
定义一个常量时用final,并且常量名要大写。比如 final float PI=3.14;
-----------------------------------------------------------------------------------------------------------------------------------------
break (中断)跳出的是当前的整个for循环
continue(继续) 是不再执行continue 以后的代码 直接进行下次循环 它并没有跳出for整个循环
-------------------------------------------------------------------------------------------------------------------------------------
Java中的四种修饰属性 public     所有包 不同子包都可以访问到
             protected  同一包可以访问到,不同一包的非子类访问不到
             default    只有在同一包下可以访问到
             private    只有自己的类中可以访问到
封装性:封装就是隐藏实现细节, 将属性私有化, 提供公有方法访问私有属性。
1用private(私有的)说明权限
 当一个属性被封装时,可以定义一个方法让外部得到或者还回这个对象,    即:getXxx()与setXxx();
2 一个方法被封装起来时 看不到方法的过程,也不知道它是怎样运行的
-----------------------------------------------------------------------------------------------------------------------------------------
方法的重载与重写
方法的重载是在一个类中 方法名相同 参数不同;
方法的重写则是在继承中 父类与子类有相同的方法 ,但方法的内容不一样。具体的实现功能由子类中的方法去写。
-----------------------------------------------------------------------------------------------------------------------------------------
如果一个子类继承了父类,那么在子类调用构造方法实例化时,必须先调用父类中的构造方法(因为子类继承了父类,父类中所有公共的属性和方法都可以被子类调用,如果子类在实例化之后需要马上用到父类中的属性或者方法,而这时候父类还没有初始化,显然是要出问题的,所有必须先初始化父类空间。)
-----------------------------------------------------------------------------------------------------------------------------------------
StringBuffer是可变的字符串对象
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据。
自动装箱即基本数据类型被自动包装为包装类在JDK5之后才有这个功能。
-----------------------------------------------------------------------------------------------------------------------------------------
this与super
this  可以代表当前类的对象
this  只是在本类中使用               super 代表调用的是父类中的成员
this. 调用本类中的属性和普通方法     super.调用父类中的属性和普通方法
this() 调用本类中的构造方法          super()调用父类中的构造方法
-----------------------------------------------------------------------------------------------------------------------------------------
final 最终的
修饰的类不能被继承
修饰的变量变为常量
修饰的方法不能被重写
-----------------------------------------------------------------------------------------------------------------------------------------
toString 方法是在输出的时候会自动调用 如果你没有重写toString方法 调用的是超类Object类中的toString方法 返回的是对象的地址
-----------------------------------------------------------------------------------------------------------------------------------------
String 的俩种实例化的区别
String str="hello";
String str2="hello";
String str3="hello";
这种直接赋值的方式 实际上只在堆内存中创建了一个“hello” str str1 str2全指向一个 “hello”。字符串的内容一旦创建则不可更改。
String str4=new String(hello);会重新开辟新空间 存储hello
str +“Word”
第一种方式会在堆内存中 创建“Word” 的空间  最后再创建一个新空间 用来存储“ hello Word”str重新指向“helloWord”。
StringBuffer str5=new StringBurberry
str5 +“Word”;
它在堆内存中不会创建新的空间,会把原来的“hello”变为“hello Word”
-----------------------------------------------------------------------------------------------------------------------------------------
String 类是不可变类
StringBuffer类是可变类,任何对它所指代的字符串的改变都不会产生新的对象。  可变与不可变是说内容是否可变
StringBuffer和StringBuilder类的区别 :StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。
采用String对象时,即使运行次数仅是采用其他对象的1/100,其执行时间仍然比其他对象高出25倍以上;而采用StringBuffer对象和采用StringBuilder对象的差别也比较明显,前者是后者的1.5倍左右。由此可见,如果我们的程序是在单线程下运行,或者是不必考虑到线程同步问题,我们应该优先使用StringBuilder类;当然,如果要保证线程安全,自然非StringBuffer莫属了。
StringBuffer和StringBuilder类长度都是可扩充的。
-----------------------------------------------------------------------------------------------------------------------------------------
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
 简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
 而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
 String S1 = “This is only a” + “ simple” + “ test”;
 StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
 你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个
 String S1 = “This is only a” + “ simple” + “test”; 其实就是:
 String S1 = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:
String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;
这时候 JVM 会规规矩矩的按照原来的方式去做

在大部分情况下 StringBuffer > String
StringBuffer
Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
在大部分情况下 StringBuilder > StringBuffer
java.lang.StringBuilde
java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
-----------------------------------------------------------------------------------------------------------------------------------------
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
多态存在的三个必要条件
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。
1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。


Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。
-----------------------------------------------------------------------------------------------------------------------------------------
static 静态的
可以修饰成员变量 ,修饰方法,修饰代码块 。无论修饰什么 在加载的时候都会被优先加载。
静态修饰的方法或者成员变量不能调用非静态的成员变量或方法,因为静态变量或方法会优先加载,找不到非静态成员变量或方法
静态成员可以统计 类被加载了几次,因为每加载一次类都会先加载静态成员  (只要静态成员+=1 输出静态成员)
-----------------------------------------------------------------------------------------------------------------------------------------
主方法为什么不能被new 因为主方法是所有程序的入口 只有加载了主方法 才能继续加载其他代码;
主方法中的数组的作用:可以添加参数,在主方法被加载的同时把这些参数传递进去
具体方法:在有主方法的类中 点击右键 Run As 选择Run Configurations  有一排选项卡有7个 选择第二个点击 在第一个文本框中 输入第一个要传进去的参数 回车 输入第二个参数,以此类推   
如何显示:在主方法中输出:
        System.out.println(args[0]);
        System.out.println(args[1]);
即可。
-----------------------------------------------------------------------------------------------------------------------------------------
向上转型与向下转型     多态的使用        Animal animal=new Cat();
向上转型是:子类-----》父类 自动转型        animal=cat;            //子类对象cat赋给父类对象animal
向下转型是:父类-----》子类 需要强制转换     cat=(Cat)animal     //父类对象animal赋给子类对象需要强制转换

可以发生向下转型的另一个因素是父类的这个对象本来就new的是cat的对象如果你new的是Dog的对象那么上面的例子向下转型就会出问题。
为什么要强制转换?
因为多态父类对象只能使用子类中覆写父类的方法,不能使用子类中特有的方法,如果想使用,则必须将父类对象转换为子类对象(也就是向下转型)才能使用子类特有的方法。

有时候给你传过来一个父类中的对象,而你不知道它new的是哪个子类那么可以使用instanceof判断。
关键字instanceof
 if(animal instanceof Cat):
这个if可以判断animal这个父类对象new的是不是子类Cat
-----------------------------------------------------------------------------------------------------------------------------------------
abstract  修饰抽象
抽象类跟普通类一样 可以定义构造方法,成员方法,成员变量,但是抽象类不能通过构造方法实例化对象,它的构造方法是用来被子类调用的。
如果一个抽象类被继承,则必须重写这个抽象类中的抽象方法,(也就是由子类具体地实现这个方法)普通方法是可以不重写的。
注意:抽象类中可以存在变量和成员方法、构造方法。变量和成员方法将会被子类继承,可以通过多态的形式访问。
-----------------------------------------------------------------------------------------------------------------------------------------
接口interface(一个接口中只有抽象方法与被抽象修饰的变量(也就是常量))
接口与接口之间可以单继承, 类与类之间也是单继承,
类与接口之间是实现。
一个类支持单继承,多实现,(必须是先继承后实现,这个顺序不能变。)也就是一个类可以继承另一个类,同时可以实现多个接口。被继承的类如果是抽象类,那么这个继承的类必须实现被继承类的抽象方法(普通方法看你需不需要,需要就继承,不需要可以不继承,如果不是抽象类,则可以选择性继承不是强制性要求,如果是抽象的类中的抽象方法,则是强制性继承),()同时实现多个接口中的抽象方法。(如果这些接口中有继承了其他接口,则其他接口中的抽象方法也必须重写在你的类中重写(注意是在实现类中重写))
一个接口如果被继承,那么必须重写这个接口中的方法,就是抽象方法。   如果你不想重写,那么好,你也必须是抽象类。咱俩的抽象方法由继承你的那个类去实现。
(比如A是一个接口,你B继承了我,就必须对我负责(继承我的方法)是吧,如果你不想负责,那么可以找C类去继承你,然后C类就必须同时对咱俩负责,这样你就不用负责了。)
-----------------------------------------------------------------------------------------------------------------------------------------
JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
-----------------------------------------------------------------------------------------------------------------------------------------
总结:抽象类和接口的区别
    共同点:
        1、都是用来实现抽象的,代表抽象层。
        2、都不能被实例化。  new
        3、都是包括抽象方法但不给出具体的实现。
    异同点:
        1、抽象类还是类,可以具备成员方法,而接口只能有抽象方法。
        2、一个类只能继承一个抽象类,但是可以实现多个接口。
        3、抽象类中添加一个普通方法,不会对子类造成影响,而对于接口,一旦公布就不应该改变。
-----------------------------------------------------------------------------------------------------------------------------------------
反射:主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
作用:1在运行时判断任意一个对象所属的类
      2在运行时判断任意一个类所具有的成员变量和方法
      3在运行时判断任意调用一个对象的方法
      4在运行时构造任意一个类的对象
什么是反射机制?
    简单说,反射机制值得是程序在运行时能够获取自身的信息,在Java中,只要有给定类的名字,那么就可以通过反射机制获取这个给定类的所有信息
Java反射机制提供了什么功能?
    在运行时能够判断任意一个对象所属的类
    在运行时构造任意一个类的对象
    在运行是判断任意一个类所具有的成员变量和方法    
    在运行时调用任意对象的方法
    在运行时创建新类对象
哪里用到反射机制?
    很多框架都用到反射机制,hibernate Struts 都是利用反射机制实现的 比较常见的有连接数据库时的代码Class.forname('com.MySql.jdbd.Driver.coass').newInstance();
反射机制的优缺点?
    静态编译:在编译时确定类型,绑定对象,通过
    动态编译:运行时确定类型,绑定对象。
    优点:反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类
    缺点:1性能问题:使用反射基本是一种解释操作。用于字段和方法接入时要远慢与直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用
          2:使用反射会模胡程序内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比响应的直接代码更复杂。
-----------------------------------------------------------------------------------------------------------------------------------------
== 比较的是对象的地址 (地址值的比较)-128到127之间返回true
equals 没有重写之前比较的是对象的地址,重写(覆写)之后调用的是this这个类型(String或者Integer类)中的equals方法
equals 比较的是字符串中的内容(内容比较)
字符串中的内容一旦申明则不可改变。
-----------------------------------------------------------------------------------------------------------------------------------------
1、栈:由JVM分配区域,用于保存线程执行的动作和数据引用,存放的是函数的参数值,局部变量的值。栈是一个运行的单位,JAVA中一个线程就会相应地有一个线程栈与之对应。具体方法执行结束之后,系统自动释放JVM内存资源。

2、堆:由JVM分配的,存放由new创建的对象跟数组,JVM不定时地查看,如果没有引用指向这个对象就会被回收(垃圾回收机制)。

3、静态区(datasegment)—存放全局变量,静态变量和字符串常量,不释放

4、代码区(codesegment)—存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域

5、常量池:在编译阶段,在堆中分配出来的一块存储区域,用于存储显示的String,float 或者integer。例如:String str=“ABC”。“ABC”这个字符串是显示申明,所以存储在常量池。

      在方法(代码块)中定义一个变量时,java就在栈中为这个变量分配JVM内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的JVM内存空间;
      在堆中分配的JVM内存由java虚拟机的自动垃圾回收器来管理,堆的优势是可以动态分配JVM内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配JVM内存的。
          缺点就是要在运行时动态分配JVM内存,存取速度较慢;
      栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。
经过测试    String str="sram";
        String str1=new String ("sram");
        System.out.println(str==str1);
返回的是false 说明常量池里的“sram”与堆内存中的“sram”是不一样的。“==”比较的是对象地址的引用
        System.out.println(str.equals(str1));
返回的是true  说明equals 比较的是对象的内容。
-----------------------------------------------------------------------------------------------------------------------------------------
String和int直接赋值的区别。首先,最大的区别,一个是对象,一个是数值,对象可以为null,数值却必须有值,哪怕你没赋值,系统也会自动赋值为0。
-----------------------------------------------------------------------------------------------------------------------------------------
一个抽象类是不能用final 修饰的 因为抽象类就是用来被继承的 必须被子类覆写 不能继承的话就没有任何意义了。
-----------------------------------------------------------------------------------------------------------------------------------------
NULL代表声明了一个空对象,根本就不是一个字符串。只不过这个空对象没有指向堆内存中任何一个地址而已。   
“”代表声明了一个对象实例,这个对象实例的值是一个长度为0的空字符串。在堆内存中是有指向的 只不过长度为0而已。
-----------------------------------------------------------------------------------------------------------------------------------------
接口的特点:
接口是对外暴露的原则(因为接口就是用来被继承的,必须被子类覆写。)
接口是程序功能的扩展
接口的出现降低耦合性
接口可以多实现
类与接口之间是实现关系,接口与接口之间是继承关系。
一个类可以继承一个类的同时实现多个接口。
-----------------------------------------------------------------------------------------------------------------------------------------
抽象类与接口共性:都是不断抽取出来的抽象的概念。
-----------------------------------------------------------------------------------------------------------------------------------------
成员变量有默认初始化的值,局部变量没有默认的初始化值,必须赋值。
-----------------------------------------------------------------------------------------------------------------------------------------
字符串与int型之间的转换,要记得包装类
-----------------------------------------------------------------------------------------------------------------------------------------
集合中只用于存储对象,长度可变。数组还可以存储基本数据类型,长度是不可变的。
    List集合:List集合可以存在重复元素,怎么放怎么拿。
        ArrayList: 数组数据结构,查找方便。
            list中是否包含某个元素;
              方法:.contains(Object o); 返回true或者false
            如果是根据某种规则判断自定义类型,需要在自定义类中重写equals方法
        Vector: 与ArrayList一样,也是通过数组实现的。不同的是它支持线程的同步,  
              即一时刻只有一个线程能够写Vector,避免多线程同时写引起的不一致性。但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
        LinkedList: 链表数据结构实现的一个可变长容器,对头尾的操作灵活,插入快,查询慢。
    Set集合:Set集合中无法存储重复元素,存取顺序不一致
        HashSet: 底层是哈希表的数据结构。
            如何判断元素不重复?
            首先判断的是元素的哈希码,如果哈希码不一致,则元素不重复。如果哈希吗一致,则用equals方法比较俩个对象,返回true则是同一个对象,反之则不是同一个对象。
        TreeSet: 底层是二叉数数据结构。
            存放入TreeSet中的元素一定会自定义排序
            放入TreeSet的元素必须按照某种排序规则排序,如果没有排序规则,需要强制給元素添加排序
            第一种排序方法需要先让类继承compareable接口 然后重写compareTO方法
            第二种,自定义一个类专门用来排序
            第三种:匿名内部(只能使用一次)
     Map集合:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。  
             HashMap  采用哈希表实现,所以无序  
             TreeMap   可以对健进行排序
-----------------------------------------------------------------------------------------------------------------------------------------
迭代器的next方法返回的值类型是object,所以要记得类型转换。
-----------------------------------------------------------------------------------------------------------------------------------------
泛型是没有办法指定基本数据类型的,必须设置成一个类

-----------------------------------------------------------------------------------------------------------------------------------------
枚举类不能继承其他类 因为枚举类已经继承了Java.lang.Enum类了

-----------------------------------------------------------------------------------------------------------------------------------------
invoke方法  参数:传一个对象,一个要调用方法的参数   返回 执行这个方法的结果  在Method类中

-----------------------------------------------------------------------------------------------------------------------------------------
多线程:Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。
    其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。
    1:继承Thread类的方法尽管是一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。
        start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。
        MyThread myThread1 = new MyThread();  
        MyThread myThread2 = new MyThread();  
        myThread1.start();  
        myThread2.start();
    2、实现Runnable接口方式实现多线程
    如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口
    为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
        MyThread myThread = new MyThread();  
        Thread thread = new Thread(myThread);  
        thread.start();
什么是线程?

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。Java在语言层面对多线程提供了卓越的支持,它也是一个很好的卖点。欲了解更多详细信息请点击这里。
2) 线程和进程有什么区别?

线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。更多详细信息请点击这里。
3) 如何在Java中实现线程?

在语言层面有两种方式。java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承java.lang.Thread 类或者直接调用Runnable接口来重写run()方法实现线程。更多详细信息请点击这里.
4) 用Runnable还是Thread?

这个问题是上题的后续,大家都知道我们可以通过继承Thread类或者调用Runnable接口来实现线程,问题是,那个方法更好呢?什么情况下使用它?这个问题很容易回答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类,当然是调用Runnable接口好了。更多详细信息请点击这里。
6) Thread 类中的start() 和 run() 方法有什么区别?

这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。更多讨论请点击这里
7) Java中Runnable和Callable有什么不同?

Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。我的博客有更详细的说明。
8) Java中CyclicBarrier 和 CountDownLatch有什么不同?

CyclicBarrier 和 CountDownLatch 都可以用来让一组线程等待其它线程。与 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。点此查看更多信息和示例代码。
9) Java内存模型是什么?

Java内存模型规定和指引Java程序在不同的内存架构、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。这个关系定义了一些规则让程序员在并发编程时思路更清晰。比如,先行发生关系确保了:

    线程内的代码能够按先后顺序执行,这被称为程序次序规则。
    对于同一个,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前,也叫做管程锁定规则。
    前一个对volatile的写操作在后一个volatile的读操作之前,也叫volatile变量规则。
    一个线程内的任何操作必需在这个线程的start()调用之后,也叫作线程启动规则。
    一个线程的所有操作都会在线程终止之前,线程终止规则。
    一个对象的终结操作必需在这个对象构造完成之后,也叫对象终结规则。
    可传递性

我强烈建议大家阅读《Java并发编程实践》第十六章来加深对Java内存模型的理解。
10) Java中的volatile 变量是什么?

volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生,就是上一题的volatile变量规则。点击这里查看更多volatile的相关内容。
11) 什么是线程安全?Vector是一个线程安全类吗? (详见这里)

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全和非线程安全的。Vector 是用同步方法来实现线程安全的, 而和它相似的ArrayList不是线程安全的。
12) Java中什么是竞态条件? 举个例子说明。

竞态条件会导致程序在并发情况下出现一些bugs。多线程对一些资源的竞争的时候就会产生竞态条件,如果首先要执行的程序竞争失败排到后面执行了,那么整个程序就会出现一些不确定的bugs。这种bugs很难发现而且会重复出现,因为线程间的随机竞争。一个例子就是无序处理,详见答案。
13) Java中如何停止一个线程?

Java提供了很丰富的API但没有为停止线程提供API。JDK 1.0本来有一些像stop(), suspend() 和 resume()的控制方法但是由于潜在的死锁威胁因此在后续的JDK版本中他们被弃用了,之后Java API的设计者就没有提供一个兼容且线程安全的方法来停止一个线程。当run() 或者 call() 方法执行完的时候线程会自动结束,如果要手动结束一个线程,你可以用volatile 布尔变量来退出run()方法的循环或者是取消任务来中断线程。点击这里查看示例代码。
14) 一个线程运行时发生异常会怎样?

这是我在一次面试中遇到的一个很刁钻的Java面试题, 简单的说,如果异常没有被捕获该线程将会停止执行。Thread.UncaughtExceptionHandler是用于处理未捕获异常造成线程突然中断情况的一个内嵌接口。当一个未捕获异常将造成线程中断的时候JVM会使用Thread.getUncaughtExceptionHandler()来查询线程的UncaughtExceptionHandler并将线程和异常作为参数传递给handler的uncaughtException()方法进行处理。
15) 如何在两个线程间共享数据?

你可以通过共享对象来实现这个目的,或者是使用像阻塞队列这样并发的数据结构。这篇教程《Java线程间通信》(涉及到在两个线程间共享对象)用wait和notify方法实现了生产者消费者模型。
16) Java中notify 和 notifyAll有什么区别?

这又是一个刁钻的问题,因为多线程可以等待单监控锁,Java API 的设计人员提供了一些方法当等待条件改变的时候通知它们,但是这些方法没有完全实现。notify()方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有用武之地。而notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。我的博客有更详细的资料和示例代码。
17) 为什么wait, notify 和 notifyAll这些方法不在thread类里面?

这是个设计相关的问题,它考察的是面试者对现有系统和一些普遍存在但看起来不合理的事物的看法。回答这些问题的时候,你要说明为什么把这些方法放在Object类里是有意义的,还有不把它放在Thread类里的原因。一个很明显的原因是JAVA提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。如果线程需要等待某些锁那么调用对象中的wait()方法就有意义了。如果wait()方法定义在Thread类中,线程正在等待的是哪个锁就不明显了。简单的说,由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。你也可以查看这篇文章了解更多。
18) 什么是ThreadLocal变量?

ThreadLocal是Java里一种特殊的变量。每个线程都有一个ThreadLocal就是每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了。它是为创建代价高昂的对象获取线程安全的好方法,比如你可以用ThreadLocal让SimpleDateFormat变成线程安全的,因为那个类创建代价高昂且每次调用都需要创建不同的实例所以不值得在局部范围使用它,如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。首先,通过复用减少了代价高昂的对象的创建个数。其次,你在没有使用高代价的同步或者不变性的情况下获得了线程安全。线程局部变量的另一个不错的例子是ThreadLocalRandom类,它在多线程环境中减少了创建代价高昂的Random对象的个数。查看答案了解更多。
19) 什么是FutureTask?

在Java并发程序中FutureTask表示一个可以取消的异步运算。它有启动和取消运算、查询运算是否完成和取回运算结果等方法。只有当运算完成的时候结果才能取回,如果运算尚未完成get方法将会阻塞。一个FutureTask对象可以对调用了Callable和Runnable的对象进行包装,由于FutureTask也是调用了Runnable接口所以它可以提交给Executor来执行。
20) Java中interrupted 和 isInterruptedd方法的区别?

interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt()来中断一个线程就会设置中断标识为true。当中断线程调用静态方法Thread.interrupted()来检查中断状态时,中断状态会被清零。而非静态方法isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛出InterruptedException异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其它线程调用中断来改变。
21) 为什么wait和notify方法要在同步块中调用?

主要是因为Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。还有一个原因是为了避免wait和notify之间产生竞态条件。
22) 为什么你应该在循环中检查等待条件?

处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。因此,当一个等待线程醒来时,不能认为它原来的等待状态仍然是有效的,在notify()方法调用之后和等待线程醒来之前这段时间它可能会改变。这就是在循环中使用wait()方法效果更好的原因,你可以在Eclipse中创建模板调用wait和notify试一试。如果你想了解更多关于这个问题的内容,我推荐你阅读《Effective Java》这本书中的线程和同步章节。
23) Java中的同步集合与并发集合有什么区别?

同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合,不过并发集合的可扩展性更高。在Java1.5之前程序员们只有同步集合来用且在多线程并发的时候会导致争用,阻碍了系统的扩展性。Java5介绍了并发集合像ConcurrentHashMap,不仅提供线程安全还用锁分离和内部分区等现代技术提高了可扩展性。更多内容详见答案。
24) Java中堆和栈有什么不同?

为什么把这个问题归类在多线程和并发面试题里?因为栈是一块和线程紧密相关的内存区域。每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域。对象都在堆里创建,为了提升效率线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,这时volatile 变量就可以发挥作用了,它要求线程从主存中读取变量的值。
更多内容详见答案。
25) 什么是线程池? 为什么要使用它?

创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池)。更多内容详见这篇文章。
26) 如何写代码来解决生产者消费者问题?

在现实中你解决的许多线程问题都属于生产者消费者模型,就是一个线程生产任务供其它线程进行消费,你必须知道怎么进行线程间通信来解决这个问题。比较低级的办法是用wait和notify来解决这个问题,比较赞的办法是用Semaphore 或者 BlockingQueue来实现生产者消费者模型,这篇教程有实现它。
27) 如何避免死锁?


Java多线程中的死锁
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足以下四个条件:

    互斥条件:一个资源每次只能被一个进程使用。
    请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
    循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

避免死锁最简单的方法就是阻止循环等待条件

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章