精华内容
下载资源
问答
  • JAVA程序设计入门读书笔记第一章、JAVA入门java历史、简单语法及运行功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定...

    JAVA程序设计入门读书笔记


    只是个人的读书记录而已

    第一章、JAVA入门

    1.1java历史、简单语法及运行

    JAVA开始的名字是Oak;可以运行在linux、win、mac所有平台
    支持单一继承、多级继承、层次继承。没有多重继承。

    类A
    类B
    **单一继承**
    类A
    类B
    类C
    **多级继承**

    区别
    1. print 与 println 的唯一区别是:
    println是在下一行显示输出。而print在同一行显示输出
    2. 访问限定符
    Public:不同包可以使用
    Default:只能在包内访问
    Protected:
    Private
    3. static:允许在不创建类实例的情况下调用main()方法

    命令行可以运行java文件。通过javac来编译程序(加后缀);通过java来执行(不加后缀)

    1.2面向对象编程

    类、实例、对象是不可或缺的。
    一旦从类中派生出了对象,就形成了一个实例。
    对象可以采用的操作 称为方法。

    数据抽象:有助于隐藏树复杂性。
    封装:方法和数据被组合成为一个单元。
    多态。一个名称,多种形式。比如方法重载
    继承。 子类 继承了 父类(超类、基类)

    第二章 java基础

    主要是标志符、关键字、数据类型、变量、转义字符、类型转换的概念。

    2.1标识符

    1,命名首字母必须是大小写字母或下划线或美元号$。一定不能是数字。
    2,之后是字母数字下划线美元号的任意组合。禁止出现非法字符
    3,java是区分大小写的。Cad 和CAD 是两个不同的变量名。
    4,关键字不可用。

    2.2 关键字

    abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while

    2.3数据类型

    java 的数据类型不同于C/C++,分配给特定数据类型的内存数量是严格定义好的,不会依赖机器架构

    整型类型 大小(字节)
    byte 1 (范围在-128~127)8位补码
    short 2 (-215~215-1)
    int 4 (-231~231-1)
    long 8

    派生数据类型: (保存多个相同类型的值)代表是数组和字符串
    例:int a[]={1,3,4}; char s[]={‘c’ , ’ b’};

    2.4转义序列

    即反斜杠(\)开始的

    转义序列 描述
    \t 插入制表符
    \ 插入反斜线
    插入单引号
    " 插入双引号
    \r 插入回车
    \b 插入退格
    \f 插入换页

    2.4 变量(variable)

    初始化一个变量,同或赋值运算完成。
    也可以动态地初始化变量。 sum = a+b

    2.5 类型转换

    隐式转换(扩大转换)和显示转换(缩小转换)
    扩大转换不会丢失信息,
    缩小转换(narrowing conversion)会丢失某些信息。
    例:int a=300;
    b = (byte)a;
    那么b=44;
    解释:因为300的二进制是100101100B;转换位8位的byte类型时,只取低8位,即44

    2.6 逻辑运算

    运算符 操作
    ~ 按位求补
    ^ 按位异或
    >> 右移(可实现除法)
    << 左移(可实现乘法)

    命令行传参数

    命令行的参数会被保存在main()方法的String类型的arg[]数组中。
    当需要数字运算时,需要将string类型转换为int类型。
    使用Integer.parseInt()方法进行转换
    类似的 Long.parseLong() 和 Float.parseFloat()

    小结:

    ☆instanceof 运算符:用于在运行时检查对象是否为指定类型(类、子类或接口)的实例。
    使用例子:boolean i = id(对象名) instanceof Instanceof_demo(类名)
    ☆变量(variable):能够保存数据的具名位置,在计算机内存中拥有特定地址
    局部变量:在代码块或方法内部声明的变量。有局部作用域。
    实例变量:在类内部(类的其他方法之外)声明的变量。

    第三章 控制语句与数组

    主要是if if-else if-else-if switch while do-while for 跳转 数组 foreach循环

    控制语句

    if for 与C一样。
    多级条件时 if else-if else-if … else

    数组

    声明:datayepe arr_name[];
    声明一个数组不会分配内存,其值被置null。要为数组分配内存,必须使用new运算定义数组。
    分配内存: arr_name = new datatype [size];

    或者可以不使用 new方法完成数组初始化。
    例:int arr_name ={ 1,3,4 };

    多维数组

    声明二维数组:data_type arr_name[][] = new data_type[size][size]

    foreach --for循环的升级版。

    for(datatype var_name : collection)
    就是一个迭代器。

    第四章 类与对象

    OOP(object-oriented programming)

    4.1类

    类是一种自定义的数据类型,使用类的目的是将数据和方法封装到单个单元中。可用于创建特定数据类型的对象,由此创建的对象称为类的实例。

    定义类
    class class_name
    {
    	datatype variable1;
    	datatype variable2;
    	datatype method1(list of arguments){
    		body of the method1;	
    	}
    	
    }
    

    4.2对象

    对象被定义为类的实例/物理实体。也叫做程序的活跃实体(live entity)

    4.2.1创建对象

    创建对象分两步。类似于数组的创建。
    ①声明②用new分配
    例:
    classname obj1;
    obj1 = new classname();
    也可以合并为
    classname obj1 = new classname();

    4.2.2初始化实例变量

    创建了不同的对象,每个对象都有自己的实例变量。使用 点号( . )运算来初始化类的实例变量。
    例:obj_name.var_name = value ot expression(初值);

    4.2.3访问实例变量

    用点号( . )

    4.3方法

    方法是用来执行特定任务的一组语句。

    4.3.1类中包含实例变量和方法。而具体的方法内容如下。

    定义方法语句
    access_specifier(访问限定符) return_type method_name(List of arguments){
    body of method;
    return value;
    }
    

    ☆ 方法的调用也是使用点号( . )

    这里在eclipse中.java文件中可以出写多个类,但是public 只能修饰一个类。

    4.3.2向方法传递参数

    传递简单数据,java值传递该数据的副本,而非原始数据。这叫做按值传递(pass by value)。更改副本不会影响到原始数据。

    access_specifer ret_type method_name(type par_name1, type par_name2)
    {
    	body of method;
    }
    ex:
    int sum(int i,int j){
    	int c = a+b;
    	...
    }
    

    4.3.3向方法传递对象

    传递 对象 不同于传递 普通数据。java按照引用传递对象,当对象作为参数传递给方法,实际上传递的是对象的引用。因此,如果改动传递的对象,会改变原始数据。

    框架
    class Demo{
    	------;
    	int area(Rect obj1, Rect obj2){
    		-----;
    	}
    }
    
    实例:矩形面积
    class Rectangle
    {
    	double length,width;
    	void getvalues(double l, double w)
    	{
    		length = l;
    		width = w;
    	}
    	void area(Rectangle obj) { //这里 传递了对象
    		double res;
    		res = obj.length*obj.width;
    		System.out.println(res);
    	}
    }
    public class passobj 
    {
    	public static void main(String[] args) 
    	{
    		Rectangle obj1 = new Rectangle();
    		obj1.getvalues(0.4, 0.7);
    		obj1.area(obj1);
    		
    	}
    }
    
    

    4.3.4从方法返回对象

    方法的return 不仅可以返回int double等简单的数据类型。也可以返回某个类的对象。

    框架:
    Demo sum()
    {
    	Demo obj = new Demo();
    	return obj;
    }
    解释:返回类型是 Demo类。只要调用sum()方法,就可返回Demo类的obj对象:
    obj2 = obj1.sum();
    

    4.3.4 向方法传递数组

    前面已经学了,传递参数时,按值传递,是副本的传递,不会影响原数据。
    而传递对象时,是传递引用类型,会改变原数据。
    现在,传递数组也是传递引用类型,同样会改变原数据。

    class Square{
    	int result;
    	void sqr(int a[]) {  //传递数组
    		for(int i =0;i<a.length;i++) {
    			result = a[i]*a[i];
    			System.out.println("square of "+a[i]+"is "+result);
    		}
    	}
    }
    
    public class PassArray {
    
    	public static void main(String[] args) {
    		int a[]= {1,3,5,7,9};
    		Square obj = new Square();
    		obj.sqr(a);
    	}
    }
    
    

    4.3.5方法重载

    当有两个或以上同名但不同参数的方法,就产生了方法重载。这是java中实现多态的一种方式。只要调用重载的方法,编译器就会根据返回类型 参数数量来区分特定的方法。如果找到了严格匹配,编译器就会执行该方法。

    class choose{
    	void doit(){
    		System.out.println("just do it");
    	}
    	void doit(int x) {
    		System.out.println("do it "+x);
    	}
    	void doit(double x) {
    		System.out.println("do it "+x);
    	}
    }
    public class OverLoad {
    	public static void main(String[] args) {
    		choose obj1 = new choose();
    		obj1.doit();
    		obj1.doit(2);
    		obj1.doit(2.0);
    	}
    }
    输出:
    just do it
    do it 2
    do it 2.0
    

    4.4构造函数

    构造函数是类的一种特殊方法,用于创建对象时对其初始化。

    框架
    class_name (list of parameters){
    	body of the constructor;
    }
    
    

    java 有三种类型的 构造函数。
    ·默认构造函数
    ·带参数的构造函数
    ·复制构造函数

    4.4.1默认构造函数(无参数的构造函数)

    例子:
    class Demo{
     int i,j;
     Demo(){
     	i=0;
     	j=0;
     }
     -----;
    }
    

    只要创建Demo类的对象,就会调用构造函数 Demo()
    Demo obj1 = new Demo();
    一调用构造函数,就将obj1对象的实例变量i和j 初始化为0。
    若一个类 中 没有定义构造函数,编译器会自动创建默认构造函数。

    4.4.2带参数的构造函数

    默认的构造函数,初始化的值是默认的、固定的。
    用不同的值来初始化不同对象的实例变量,可以使用带参数的构造函数。在创建对象是传入参数。

    例子:
    class Demo{
     int i,j;
     Demo(int x,int y){
     	i=x;
     	j=y;
     }
     -----;
    }
    

    4.4.3复制构造函数

    把一个对象的值复制到另一个对象。

    例子:
    class Demo{
     int i,j;
     Demo( Demo obj){
     	i=obj.i;
     	j=obj.j;
     }
     -----;
    }
    

    4.4.4构造函数重载

    class Demo
    {
    	int i, j;
    	Demo()
    	{
    		i =0;
    		j =0;
    	}
    	Demo(int x)
    	{
    		i = j =x;
    	}
    	Demo(int x, int y)
    	{
    		i = x;
    		j = y;
    	}
    	---;
    	---;
    }
    

    Demo被重载了三次。根据参数来决定具体的构造函数

    4.4.5垃圾回收

    某些面向对象语言(C++)中,需要手动回收用不到的内存,用delete等运算符。但Java提供了一套内存自动回收机制。称为垃圾回收。由Java环境来实现。
    当不存在对特定对象的引用,该对象就具备了被回收的条件。
    在程序执行期间,Java运行时环境以固定的间隔自动运行垃圾回收器。也可以用System类的gc()方法来手动实现

    4.4.6finalize()方法

    不在使用的对象会进入垃圾回收器被销毁。但销毁前还可以通过finalize方法发来执行某些操作。
    finaize方法 的目的在于释放对象用到的一些非java资源。也称之为清理方法。

    protected void finalized(){
    	//finaization code
    }
    

    4.4.6this 关键字

    this关键字用于指定类的当前对象。当方法或构造函数需要引用调用其的对象时,this关键字就可使用了。我们也可以使用这个关键字在方法或构造函数内引用当前对象的任何实例变量。

    Rectangle(double l,double w){
    	this.length = l;
    	this.width = w;
    }
    Rectangle obj1 = new Rectangle(23.4,43.2);
    

    4.4.7静态数据成员方法static

    static方法只能访问static数据成员和static方法。但this关键字不能在static方法中使用。

    第五章 继承

    本章将学到 继承 访问限定符、super、overriding、抽象类、final关键字

    5.1继承基础

    使用已有类的属性创建 新的类 的过程叫做继承。
    继承了其他类属性的类 称为 子类,被继承属性的类成为父类。
    使用继承的优势是代码的重用性,不必重复编写相同的代码。
    子类从父类处继承大多数属性,同时添加一些自己的属性。

    在这个过程中,父类作为一般类,只包含通用属性。
    如果子类显示继承某个类,在该类为直接父类。如果子类非显示继承某个类,两个类在层次结构中相隔两层及以上,则为间接父类。
    所有类都继承于 object 类

    5.1.1单一继承

    类继承于单一基类

    	class A
    	{
    		int a,b;
    		int sum(){
    			-----;
    		}
    	}
    	class B extends A  //继承 extends
    	{
    		-------;
    	}
    
    程序实例:
    class Box{
    	double length,width,height;
    	void display() {
    		System.out.println(length+" "+width+" "+height);
    	}
    
    }
    class SingleInheritance extends Box{
    	double result;
    	void colume() {
    		result = length*width*height;
    		System.out.println(result);
    	}
    	
    	public static void main(String[] args) {
    		SingleInheritance obj1 = new SingleInheritance();
    		obj1.height=1;
    		obj1.width=2;
    		obj1.length =1;
    		obj1.colume();
    		obj1.display();
    	}
    }
    
    
    

    5.1.2 多级继承

    子类也可以作为其他类的父类。

     class A
     {
     -------;
     }
     class B extends A
     {
     -------;
     }
     class C extends B
     {
     ------;
     }
    
    程序实例:
    class GF{
    	int roll_num;
    	void get_rollnum(int x) {
    		roll_num = x;
    	}
    	void show_roll_name() {
    		System.out.println(roll_num);
    	}
    	
    }
    
    class F extends GF{
    	double math, physics, chemistry;
    	void get_marks(int a,int b,int c) {
    		math = a;
    		physics = b;
    		chemistry = c;
    	}
    	void show_marks() {
    		System.out.println(math+" "+physics+" "+chemistry);
    	}
    }
    public class Multilevel_Inheritance extends F{
    	double res;
    	void calculate_result() {
    		res = (math+physics+chemistry)/3;
    	}
    	void show_result() {
    		System.out.println(res);
    	}
    	public static void main(String[] args) {
    		Multilevel_Inheritance obj = new Multilevel_Inheritance();
    		obj.get_rollnum(101);
    		obj.get_marks(79, 80, 81);
    		obj.show_roll_name();
    		obj.show_marks();
    		obj.calculate_result();
    		obj.show_result();
    	}	
    }
    

    5.1.3层次继承

    多个子类从一个父类处继承属性。这种情况下,父类只有一个,而子类有多个。

    class A
    {}
    class B extends A
    {}
    class C extends A
    {}
    
    class comment{
    	int num;
    	void get_value(int x) {
    		num = x;
    	}
    	void show_num() {
    		System.out.println("num is "+num);
    	}
    }
    class sqr extends comment{
    	
    	int res1;
    	void show_sqr() {
    		res1= num*num;
    		System.out.println("sqr is "+res1);
    	}
    	
    }
    class cube extends comment{
    	int res2 ;
    	void show_cube() {
    		res2= num*num*num;
    		System.out.println("cube id "+res2);
    	}
    }
    public class HierarchicalInheritance {
    	public static void main(String[] args) {
    		sqr obj1 = new sqr();
    		cube obj2 = new cube();
    		obj1.get_value(2);
    		obj1.show_num();
    		obj1.show_sqr();
    		
    		obj2.get_value(3);
    		obj2.show_num();
    		obj2.show_cube();
    	}
    }
    

    num is 2
    sqr is 4
    num is 3
    cube id 27

    5.1.4多重继承

    java不支持多重继承。一个类不能继承多个父类的属性。

    5.1.5混合继承

    java不支持混合继承。不能多种类型的继承结合到一起。

    5.2 访问限定符与继承

    对实例变量、方法或类 来使用方法限定符的作用是 定义其对于类的其他部分以及其他类的可见性。

    5.2.1 private

    声明为 private,则该成员只能在定义其的类中使用。
    一个类声明为 private,该类就不能作为父类,不能继承改类的属性。

    5.2.2 public

    声明为public,该成员在程序任何位置都可访问。

    5.2.3 protected

    声明为protected,可以在所在类及其子类中使用该成员。在相同包的其他类也可以访问。

    5.2.3 default

    没有指定任何访问限定符,则为其分配default限定符。
    在定义类的时候,建议将所有的实例变量声明为private,方法声明为public

    5.3super关键字

    5.3.1调用父类构造函数

    在子类构造函数中,super()语句 要做 第一句,否则会编译错误。

    class A
    {
    	A(int a,int b){---}
    	---;
    }
    class B extends A
    {
    	B(int x, int y, int z)
    	{super(x,y)}
    }
    
    class A{
    	private int num;
    	A(int x){ //A的构造函数。
    		num = x;
    	}
    	public void show_num() {
    		System.out.println(num);
    	}
    }
    class B extends A{
    	private int value;
    	B(int a, int b){
    		super(a);//使用super关键字调用父类A构造函数,将a作为参数传入。 a的值赋给x。
    		value =b;
    	}
    	public void show_val() {
    		System.out.println(value);
    	}
    }
    
    public class Test_super {
    	public static void main(String[] args) {
    		B obj = new B(10, 20);
    		obj.show_num();
    		obj.show_val();
    	}
    }
    

    10
    20

    5.3.2使用super关键字访问成员

    框架
    class A
    {
    	int x;
    	----;
    }
    class B extends A
    {
    	int x;
    	---;
    	super.x =a;
    	x = b;
    }
    
    实例
    class AI{
    	int v1,v2;
    }
    class BI extends AI{
    	int v1,v2;
    	BI(int a, int b, int c ,int d){
    		super.v1 =a;
    		super.v2 = b;
    		v1 = c;
    		v2 = d;
    	}
    	void display() {
    		System.out.println("superclass variable are"+super.v1
    		+" "+super.v2);//这里使用super访问父类变量
    		System.out.println("subclass variable are"+v1+" " + v2);
    	}
    }
    
    public class Test_super2 {
    	public static void main(String[] args) {
    		BI obj = new BI(12, 23, 34, 45);
    		obj.display();
    		
    		
    	}
    }
    
    

    5.4方法重写

    在子类中,定义的方法与父类方法同、同类型、同参数数量,那么新的方法会将旧的方法隐藏。这就是重写(overriding)。注意区分方法重载。

    框架
    class A
    {
    	void show(int x){
    	 ------;
    	}
    }
    class B extends A{
    	void show(int y){
    		super.show(20);
    		//调用父类A的show()方法
    	}
    }
    
    实例
    class Rect{
    	double l, w;
    	Rect(double length, double width){
    		l = length;
    		w = width;
    	}
    	double area() {
    		return l*w;
    	}
    }
    
    class overriding extends Rect {
    	double h;
    	overriding(double a,double b,double c){
    		super(a, b);
    		h = c;
    	}
    	double area() //方法重写
    	{
    		return 2*(l*w+l*h+w*h);
    	}
    	
    	void show_message() {
    		double res;
    		res = super.area(); //利用super 访问父类 方法
    		System.out.println(res);
    		res = area();
    		System.out.println(res);
    	}
    	public static void main(String[] args) {
    		overriding obj = new overriding(14, 10, 6);
    		obj.show_message();
    	}
    
    }
    

    140.0
    568.0

    5.5动态方法分配

    动态方法分配是java的一个独特的特性,也称为运行时多态。
    如果父类的引用变量引用的是 子类对象 ,则称为向上转型(upcasting)

    实例:
    class Super{
    	void display() {
    		System.out.println("super1");
    	}
    }
    class Sub extends Super{
    	void display() {
    		System.out.println("sub1");
    	}
    }
    class S extends Sub{
    	void display() {
    		System.out.println("sub2");
    	}
    }
    public class Dynamic_method_dispatch {
    	public static void main(String[] args) {
    		Super obj1 = new Super();
    		Sub obj2 = new Sub();
    		S obj3 = new S();
    		Super s; // s被声明为 Super类型的引用。
    		s = obj1;//将Super对象 赋给 s。 <向上转型>
    		s.display();
    		s= obj2;
    		s.display();
    		s = obj3;
    		s.display();
    	}
    }
    

    5.6抽象方法

    父类中包含着其所有子类的共有属性。
    但是,有时候,要求父类只能提供结构,而不是完整的实现。这种情况下父类必须使用abstract声明为抽象类。
    抽象类无法实例化只能供其子类继承。

    同样也有抽象方法。这种方法只有声明部分,没有实现。

    框架 不需要大括号
    abstract return_type method_name (parameter list);
    
    实例:
    abstract class Shape{//抽象类 提供结构
    	abstract double area();//抽象方法只是声明
    }
    class Rectan extends Shape{
    	double l,w;
    	Rectan(double length, double width){
    		l = length;
    		w = width;
    	}
    	@Override
    	double area() {
    		return l*w;
    	}
    }
    public class abstract_test {
    	public static void main(String[] args) {
    		Rectan obj = new Rectan(20, 10);
    		double res;
    		res = obj.area();
    		System.out.println(res);
    	}
    }
    

    200.0

    5.7final关键字

    final 关键字是一个保留字,用于限制用户。
    其使用目的有三:
    1.将变量声明为常量
    2.避免重写
    3.避免继承

    5.7.1.将变量声明为常量(修饰变量)

    可以用final 关键字将变量声明为常量,只能为final变量赋值一次,之后不能再被改动。
    final int i = 10;
    i初始化为10,在整个程序中不变。

    5.7.2.避免重写(修饰方法)

    有时候避免父类的方法被子类重写,可以用final关键字声明指定方法。

    class A
    {
    	----;
    	final double area(){  //final 修饰,无法被子类重写。
    		---;
    	}
    }
    class B extends A{
    	---;
    }
    

    5.7.3.避免继承(修饰类)

    类可以通过继承来重用父类的代码或属性。加上final声明后,不能被继承。
    final类中的方法是final方法。

    final class A{
    	-----;
    	void area(){
    		---;
    	}
    }
    

    总结对比:
    abstract 抽象类 提供结构,可以继承,不能实例化

    final 常量 一定终局;
    final 方法 不可重写;
    final 类 不可继承;

    第六章 包、接口和内部类

    第五章学了父类和子类的概念。本章学习object类。object类是java中所有类的父类。
    在另一个类中定义的类称为内部类(inner class)
    包(package)被视为类的容器,还可以用于提供访问保护和名称空间管理。

    6.1Object类

    java所有的类都派生于 Object类。Object类位于类层次结构的顶端。
    Object 提供了一些特定的方法。

    方法 描述
    protected object clone() 从已有类中创建新对象
    boolean equals( Object obj) 比较两个对象的内容
    protected void finalize() 每当要清除对象时,垃圾回收器会调用该方法
    Class getclass() 运行时 返回对象的类
    int hashCode() 返回调用对象 (invoking object)的散列值(hasecode)
    void notify() 唤醒等待调用对象的单个线程
    void notifyAll() 唤醒等待调用对象的所有线程
    String toString() 以文本方式返回表示对象的字符串
    void wait() 使当前线程进入等待状态
    void wait(long time)
    void wait(long time ,int nanosecond)

    6.2包

    包就是类的容器,提供了命名和访问保护控制。
    不仅能在包中定义类,还可以控制类对于相同包中其余部分的可见性。
    java中有 内建包(如 java.io.* 、java.lang.*) 和 用户自定义包 两种。

    6.2.1定义包

    定义或创建包。
    将 package pack_name; 作为java 程序的第一句。
    如果某个类是在包中声明的,则该类只属于此包。但如果声明类时未定义包,则该类归属于默认包java.lang。
    java程序中只能包含一个package语句。

    6.2.2访问包

    创建包时,java会将其保存在文件系统目录中。默认情况下,java会在当前工作目录下创建子目录来保存新创建的包。java会创建与包同名的子目录。

    6.2.3包内部的访问保护

    可见性控制。

    类和包 public private protected default
    相同类
    相同包的子类
    相同包非子类 是*
    不同包的子类 是* 否*
    不同包非子类

    6.2.4导入包

    在其他程序中使用包中的某个或所有类,使用import。
    import 中使用 * 会增加编译时间。最好是明确指定每个类

    员工信息程序
    package package_pro;  //包名
    public class Details_1 {
    	String  name;
    	int emp_id;
    	long salary;
    	public Details_1(String n, int i ,long s) {
    		name = n;
    		emp_id = i;
    		salary = s;
    	}
    	void display() {
    		System.out.println("name is "+name);
    		System.out.println("id is "+emp_id);
    		System.out.println("salary is " + salary);
    	}
    }
    
    调用实例:
    import package_pro.Details_1;
    public class Emp_demo_1 {
    	public static void main(String[] args) {
    		Details_1 obj1 = new Details_1("chen", 101, 1010);
    		obj1.display();
    	}
    }
    
    

    6.3接口

    C++提供了多重继承。在多重继承中,单个类可以继承多个类的属性。
    java不支持多重继承。Java提供了 接口。
    接口类似于抽象类,不实现具体的方法,而是只给出声明部分。就是说:接口定义了由类完成的任务,但不指定具体的做法。

    6.3.1定义接口

    定义时,要使用interface关键字,此外和类的定义没有区别。
    接口中声明的变量可以是 static 或 final类型

    框架
    access_specifier interface interface_name{
    	return_type method_name1(parameters list);
    	return_type method_name2(parameters list);
    	final data_type var_name = value;
    	return_type method_name3(parameters list);
    }
    
    实例:
    public interface demo{
    	void show();
    	int sqr();
    	final int num = 10; //之后无法修改
    }
    

    6.3.2实现接口

    定义完接口,其他类就可以在定义语句中使用 implements关键字来实现接口。

    	access_specifier class class_name [extends superclass] 
    	implements interface_name
    	{
    	-----;
    	}
    

    上面,interface_name 定义的接口由class_name代表的类来实现。接口声明的所有方法应付由该类来实现。

    类可以实现多个接口。要使用 , 分隔

    access_specifier class class_name implements interface1, 
    interface2,interfaceN
    {
    	------;	
    }
    
    程序实例:
    interface Calculate{  //定义接口
    	long fact(int num); //阶乘
    	long sqr(int n); //平方
    	
    }
    
    public class interfacedemo_2 implements Calculate{ //实现接口
    	@Override
    	public long fact(int num) {
    		int a = 1;
    		while(num>0) {
    			a = num*a;
    			num--;
    		}
    		return a;
    	}
    	@Override
    	public long sqr(int n) {
    		return n*n;
    	}
    	
    	public static void main(String[] args) {
    		long fac, sq;
    		interfacedemo_2 obj1  = new  interfacedemo_2();
    		fac = obj1.fact(4);
    		sq = obj1.sqr(2);
    		System.out.println(fac +" "+ sq);
    	}
    
    }
    

    24 4

    6.3.3接口变量

    接口不能像类一样,使用new 来创建接口的对象。但是可以创建接口变量,引用实现该接口的类作为对象。

    	long fac, sq;
    	Calculate obj  = new  interfacedemo();
    

    如上面例子中obj被声明为 接口calculate的变量,引用的是实现该接口的interface_demo类的对象。

    6.3.4扩展接口

    第五章是类的继承,使用extends关键字。
    接口也可以使用extends来继承另一个接口的属性。如果类实现了某个接口,这个类必须实现继承的所有接口的所有方法。

    interface mathmatical{
    	int sum(int a, int b);
    	long mul(int num1, int num2);
    }
    interface reminder extends mathmatical{  //扩展接口
    	int remd(int a, int b);
    }
    
    class Extend_interface_1 implements reminder{
    	@Override
    	public int sum(int a, int b) {
    		return a+b;
    	}
    	@Override
    	public long mul(int num1, int num2) {
    		return num1*num2;
    	}
    	@Override
    	public int remd(int a, int b) {
    		return a%b;
    	}
    	public static void main(String[] args) {
    		int sum,remd;
    		long mul;
    		Extend_interface_1 obj = new Extend_interface_1();
    		 
    		sum = obj.sum(2, 4);
    		mul = obj.mul(3, 4);
    		remd = obj.remd(8, 3);
    		System.out.println(sum + " "+ mul + " " + remd);
    	}
    }
    

    6.3.5嵌套接口

    在其他类 或 接口中声明一个接口,称为成员接口或嵌套接口。可以用任意的访问限定符来声明。

    嵌套接口
    public interface Outer
    {
    	//接口主体
    	public interface Inner
    	{
    		//接口主体
    	}
    }
    Outer是接口,Inner 接口代表其中的成员。
    
    实现嵌套接口
    class A implements Outer.Inner
    {
    	//类主体
    }
    
    成员接口
    class Demo{
    	//类主体
    	public interface Inner{
    		//接口主体
    	}
    }
    Inner在Demo类中声明,被称为成员接口。
    
    实现成员接口
    class A implements Demo.Inner
    {
     	//类主体
    }
    
    嵌套接口实例:
    class Outer{
    	public interface member{
    		void getdata (int n);
    		void sqr();
    		void showdata();
    	}
    }
    public class Nested_demo_2 implements Outer.member{
    	int num, res;
    	@Override
    	public void getdata(int n) {
    		num = n;
    	}
    	@Override
    	public void sqr() {
    		res = num * num;
    	}
    	@Override
    	public void showdata() {
    		System.out.println(res);
    	}
    	public static void main(String[] args) {
    		Nested_demo_2 obj = new Nested_demo_2();
    		obj.getdata(4);
    		obj.sqr();
    		obj.showdata();
    	}
    }
    
    

    6.4嵌套类

    在其他类中定义的类称为嵌套类。这种类强化了安全机制与及代码的可读性和可维护性。
    嵌套类分为1.静态嵌套2.非静态嵌套

    6.4.1静态嵌套类

    静态嵌套类时外围类的静态成员。以static关键字声明。这种类只能访问外围类的static 成员,无法访问实例成员。因此,静态嵌套类很少使用。

    class outer
    {
    	static class static_nested
    	{
    	---;
    	}
    }
    上面例子中,outer代表外围类,其中static关键字定义了static_nested类。
    可以把外围类称为前缀,创建静态嵌套类的对象。
    例:
    outer.static_nested obj = new outer.static_nested();
    
    public class Static_demo_3 {
    	static int area, l ,b;  //只能访问外围类的static成员	
    	static class Inner{
    		Inner(int len, int wid){
    			l = len;
    			b = wid;
    		}
    		void show() {
    			area = l*b;
    			System.out.println(area);
    		}
    	}
    	
    	public static void main(String[] args) {
    		Static_demo_3.Inner obj = new Static_demo_3.Inner(3, 4);
    		obj.show();
    	}
    }
    

    6.4.2非静态嵌套类

    非静态嵌套类用的更多。类不能声明为private,但是在外围类的 内部类可以这样声明。这样可以隐藏内部类。因此,内部类可以直接访问外围类的所有实例成员(包括私有成员),但外围类无法直接访问内部类的成员。
    Java有三种非静态嵌套类
    成员内部类
    局部内部类
    匿名内部类

    6.4.2.1成员内部类

    一个非静态类在另一个类之中,但又在其他方法之外声明的,该类叫成员内部类。

    class outer
    {
    	----;
    	class member_inner //外围类outer的一个成员,代表内部类
    	{
    		----;
    	}
    }
    创建内部类的对象,需要先创建外围类的对象。声明内部类对象时
    要使用外部类和内部类的引用。
    为了初始化内部类对象,要把外部类的对象放在new关键字之前。
    例子:
    outer obj = new outer();
    outer.member_inner in_obj  = obj.new member_inner
    
    成员内部类的实例。
    public class member_inner_2 {
    	int res;
    	class Inner{
    		int i, j;
    		Inner(int x, int y){
    			i = x;
    			j = y;
    		}
    		void add() {
    			res = i+j;
    			System.out.println(res);
    		}
    	}
    	public static void main(String[] args) {
    		member_inner_2 obj = new member_inner_2();
    		Inner in_obj =  obj.new Inner(4, 6);
    		in_obj.add();
    	}
    }
    
    

    6.4.2.2.局部内部类

    一个非静态类在另一个类方法中定义,则该类称为局部内部类。作用域有限,不能加访问限定符。要调用局部内部类的方法,必须在方法中创建该类的对象

    class Outer
    {
    	---;
    	void declare()
    	{
    		class  local_inner
    		{
    			---;
    		}
    		local_inner L = new local_inner();//创建对象。
    	}
    	
    }
    
    局部内部类实例:
    class local_inner_3{  //外围类
    	int cube, num;
    	void show() 
    	{
    		class Inner  //Inner类在show()方法中声明,受show()方法限制。
    		{
    			Inner(int x){
    				num = x;
    			}
    			void cube() {
    				cube = num*num*num;
    				System.out.println(cube);
    			}
    		}
    		Inner ob = new Inner(5);//创建对象
    		ob.cube();
    		
    	}
    	public static void main(String[] args) {
    		local_inner_3 obj = new local_inner_3();
    		obj.show();
    	}
    }
    

    6.4.2.3匿名内部类

    声明内部类的时候没有使用类名,则该类称为匿名内部类。这种类的声明和实例化同时完成的。匿名内部类可用于重写其他类的方法

    class outer
    {
    	----;
    	public static void main(Stringt[] args)
    	{
    		Annoymous_demo a = new Annoymous_demo() 
    		{//声明并实例化
    			void demo()
    			{---;}
    		};
    		a.demo(); //该方法调用匿名类。
    	}
    }
    
    class Annoymous_demo{
    	void demo(){
    	}
    }
    
    

    Annoymous_demo实在实例化时声明的匿名内部类,a为匿名内部类的实例。如果使用实例a调用demo()方法,Annoymous_demo类的demo()方法会被匿名内部类的该方法重写。

    匿名内部类实例:
    class anonymous_inner_4 {
    	int num = 15, sqr;
    	public static void main(String[] args) {
    		anonymous_inner_4 obj = new anonymous_inner_4();
    		Square s = new Square()    //定义匿名内部类
    						//声明并实例化了匿名类square
    		{
    			void calculate() {
    				obj.sqr = obj.num*obj.num;
    				System.out.println(obj.sqr);
    			}
    		};
    		s.calculate();  //调用匿名类的方法
    	}
    }
    class Square{
    	void calculate(){
    	}
    }
    

    第七章 异常处理

    程序运行可能会出现反常,正常的流程 可能会被打破。这种情况就是异常或运行时错误。java不必手动处理异常,可以在异常处理机制的帮助下轻松处理。

    7.1异常处理机制

    只要在方法或代码执行过程中出现异常,就会产生一个对象。异常就是一种对象,描述了相关的错误。
    异常会抛出引发错误的方法,该方法有自己处理和交给其他方法处理 这两种方式。这两种情况java运行时环境都会搜索用于处理异常的代码块。如果找到,就将异常交给其处理。处理异常的代码块称为 处理器(handler),这个过程称为异常处理。

    7.1.1异常类

    对Throwable类的子类对象, 在异常产生式,会生成异常对象并抛出方法。
    Throwable类的两个直接子类分别是 Exception和 Error。
    Exception类能够在程序内轻松捕获并处理的反常情况。
    Error类定义了普通Java程序无法处理的异常。
    插个图

    7.1.2异常类型

    包含两种异常。
    ·受检异常(check exception):发生程序编译期间。EOFException
    ·免检异常(uncheck exception):发生在运行期间。由Java自身处理。NullPointerException, IndexOutOfBoundsException

    7.1.3异常处理机制中用到语句块

    ·try
    ·catch
    ·throw
    ·throws
    ·finally

    7.1.3.1try

    用于产生异常

    try
    {
    	//用于监视错误或异常的语句
    }
    

    7.1.3.2catch

    catch用来捕获try语句块产生的异常。它作异常处理器
    catch 或 finally语句要与try语句连用。

    catch(ExceptionType obj)
    {
    	//处理异常的语句
    }
    
    可以多个catch语句
    try
    {
    	//受监视语句
    }
    catch(ExceptionType1 obj)
    { 	//处理1
    }
    catch(ExceptionType2 obj)
    { 	//处理2
    }
    -----catch(ExceptionTypen obj)
    { 	//处理n
    }
    
    嵌套try 语句。内部try未产生异常,再检查下一个try。 
    内部try没有匹配,再检查外部try
    
    try  //外围try
    {
    	try //内部try
    	{
    
    	}
    	catch(ExceptionType e)
    	{ //handle exception } 
    }
    catch(ExceptionType e)
    {
    	//handle exception
    }
    
    public class nested_try_6 {	
    	
    	public static void main(String[] args) {
    		int num=10;
    		int a = args.length;
    		int ar[]= {12, 23, 35, 46, 78};
    		try {
    			int reslut = num/a;
    			System.out.println("after division, the result is "+reslut);
    			try {
    				for(int i=0;i<=5;i++) {
    					System.out.println("value is"+ar[i]);
    				}
    			}
    			catch(ArrayIndexOutOfBoundsException e){
    				System.out.println("an exception "+e);
    			}
    		
    		}
    		catch(ArithmeticException e) {
    			System.out.println("an exception "+e);
    		}
    		
    		
    	}
    }
    
    

    当命令行运行 java nested_try_6 时,an exception java.lang.ArithmeticException: / by zero
    当运行java nested_try_6 1 2时,
    after division, the result is 5
    value is12
    value is23
    value is35
    value is46
    value is78
    an exception java.lang.ArrayIndexOutOfBoundsException: 5

    7.1.3.3throw

    catch语句块 只处理Java运行时环境抛出的异常。但 程序也可以使用throw语句显示抛出异常

    throw ThrowableOjecter;
    

    只能抛出ThrowableOjecte类或其子类的对象。抛出其他类会报错。
    程序遇到throw语句,执行完该语句之后,程序会显示错误消息。所有后续语句都被跳过,并将控制转移到最近的try-catch语句。直到检查完所有的catch语句。如果没有catch 能够处理该异常,默认方法就是挂起程序。

    class throw_2 {
    	public static void main(String[] args) {
    		int a = Integer.parseInt(args[0]);
    		int b = Integer.parseInt(args[1]);
    		try
    		{
    			if (b == 0) {
    				throw new ArithmeticException("demo");
    			}
    			else 
    			{
    				int res = a%b;
    				System.out.println("the result id "+res);
    			}
    		}
    		catch (ArithmeticException e) {
    			System.out.println("Thrown exception is "+e);
    		}
    		
    	}
    }
    这里遇到小问题,命令行运行时,由于有包package名,在src文件夹下执行命令行要使用相对路径,因为每一个包都是一个子文件夹。javac编译和java 执行都要。
    

    7.1.3.4throws

    有时候方法会产生无法处理的异常。这种情况下,该方法应指定程序的其他部分或调用者,保护其免受异常的影响。
    为此,该方法应在方法声明语句中使用throws关键字,指定方法要抛出的异常类型。

    returntype method_name(parameter list) throws exception1,exception2,....exceptionN
    {
    //方法主体部分
    }
    

    exception1…N表示该方法会抛出的异常类型。

    例子:
    static void demo(int a, int b) throws IllegalAccessException
    {
    	----;
    	throw new IllegalAccessException("trail");
    }	
    

    这个例子中demo方法会抛出IllegalAccessException类型的异常。但却无法处理该异常。

    throws程序实例
    public class throws_3 {
    	
    	static	void demo() throws NoSuchMethodException{
    		System.out.println("Inside demo method");
    		throw new NoSuchMethodException("Trial");
    	}
    	
    	public static void main(String[] args) {
    		try {
    			demo();
    		} catch (NoSuchMethodException e) {
    			System.out.println(e);
    		}
    	}
    }
    
    

    7.1.3.5finally

    当try语句块中产生异常,会改变程序的正常执行流程,跳过try语句块中某些语句。这种情况下,一些资源(文件、数据库)无法正常关闭。因此,其他程序或者同一程序中的其他部分就不能使用这些资源。
    为了避免此问题,Java采用了finally 子句。该子句中的代码负责释放try语句块中获取到的资源。注意:仅当try语句存在时,才能使用finally子句。
    当finally子句在try-catch语句块之后,无论是否发生异常,都会执行finally子句中的语句。

    try
    {
    	//受监视语句
    }
    catch(ExceptionType1 obj)
    { 	//处理1
    }
    catch(ExceptionType2 obj)
    { 	//处理2
    }
    finally
    {
    	//语句;
    }
    -----;
    如果没有catch语句,finally子句将紧随try语句之后放置
    
    finally 子句 实例
    public class finally_4 {
    
    	public static int sqr(int n) {
    		try {
    			int result = n*n;
    			if(result == 0) {
    				throw new ArithmeticException("demo");
    			}
    			else {
    				return result;
    			}
    		}
    		finally {
    			System.out.println("Inside the finally block");
    		}
    	}
    	
    	public static void main(String[] args) {
    		int sq;
    		int val = 0;
    		try {
    			sq = sqr(val);
    			System.out.println("the result is "+sq);
    		}
    		catch (Exception e) {
    			System.out.println(e);
    		}
    	}
    }
    

    Inside the finally block
    java.lang.ArithmeticException: demo

    7.1.4定义自己的异常子类

    可以创建自己的异常类并根据需要对其进行处理。通过exception 类的子类来实现。

    class class_name extends Excetion
    {
    //类的主体;
    }
    

    定义了exception的子类,该类基本上会继承throwable类的所有方法,因为exception类没有定义自己的任何方法,其全部方法来源于throwable类。

    自定义异常类
    package exceptions;
    class new_demo extends Exception{
    	public String getLocalizedMessage() {
    		return "Exception occurs";
    	}
    }
    class new_demo_5
    {
    		static void demo(int age)throws new_demo{
    			if(age<=0) {
    				throw new new_demo();
    			}
    			else {
    				System.out.println("No exception occured");
    			}
    		}
    		public static void main(String[] args) {
    			
    			try {
    				demo(10);
    				demo(0);
    			}
    			catch(new_demo e){
    				System.out.println("catch "+e);
    			}
    		}	
    }
    

    No exception occured
    catch exceptions.new_demo: Exception occurs

    类方法 记录。

    ☆ Math 类 直接用。 计算圆面积用到了 Math.PI 。
    ☆ 类方法中,赋值操作最好单独写一个getvalue函数。这样形式规整,方便读程序。

    例:
    class Test{
    	int value;
    	void getvalue(int x){
    		value = x;
    	}
    }
    

    duck不必。可以直接构造函数,constructor

    注意:命令行传递参数args数组时,用空格分隔不同元素。
    例如:
    java program_name abcd
    传入的args数组长度为0,args[0]等于’abcd’
    java program_name a b c d
    传入的args数组长度为4,args[0]等于’a’

    展开全文
  • 高并发程序设计这本书从浅入深,首先从并发的基础概念(同步异步、并发并行等等)开始,让读者对于并发有一个比较浅显的认识,然后讲述了并行程序的基础——线程,这里主要讲了一下线程的相关状态和相关的操作,然后...

         高并发程序设计这本书从浅入深,首先从并发的基础概念(同步异步、并发并行等等)开始,让读者对于并发有一个比较浅显的认识,然后讲述了并行程序的基础——线程,这里主要讲了一下线程的相关状态和相关的操作,然后提了几个可能会因为线程而出问题的错误。接下来讲了一下Java中比较常用的并发包里的类,包括锁、线程池、以及一些并发容器。第四章介绍了一些有关锁的概念以及如何通过优化锁来提高性能,比如锁粗化、所分离等等,另外,JVM本身也对锁进行了一系列的优化,这个下面会详细讲一下。除此之外,这一章还详细讲解了无锁的相关概念和原理,着重通过原子类来说明CAS操作。第五章讨论了一些并行模式以及并行算法。


    走进并行世界

    并行相关概念

    并发和并行:并发是指程序在同一个时间段内顺序发生。并行是指程序在同一时间点发生。

     同步和异步:同步是指程序执行是必须按照顺序执行,必须是一段代码返回结果之后才能执行下一段代码。异步调用不必等到结果返回,结果返回时会通知调用线程。

    临界区:多个线程访问的共享资源,但是每次只能有一个线程访问,不然可能会出错。

    阻塞和非阻塞:阻塞意味着一个线程的执行可能会影响其他线程的执行,比如它获得了所之后其他线程就只能等待它释放锁。非阻塞则是多个线程之间不会互相影响。

    死锁、饥饿和活锁:死锁可能是由于多个线程顺序推进不当造成的,他们互相持有对方所需要的资源并且等待对方释放自己需要的资源。饥饿是指线程由于优先级的存在,可能有些低优先级的线程一直都没有时间片执行。活锁是指资源在线程之间相互跳动而导致线程都不能执行。

    并发级别

    阻塞: 通过加锁的方式来对临界资源进行操作。

    无饥饿:采用公平锁的方式,所有线程都有机会执行。

    无障碍:所有线程都可以修改临界区资源,一旦发生冲突双方都立即回滚。

    无锁:线程不断尝试修改临界变量,发生冲突后会尝试重试。通过CAS操作进行修改。

    JMM模型

    原子性:操作是一步完成的,不可中断。在多线程的情况下,这种操作不会受其他线程影响。

    可见性:由于每个线程都有自己的一个缓存空间,每次取数据和放数据不一定都会在主内存中进行。可见性是指一个线程修改了一个变量,其他线程可以立刻感知这个线程对变量的修改,Java中可以通过volatile关键字来保证变量在线程之间可见。

    有序性:并发时由于指令重排序的存在可能会导致程序在多线程之间无序,也就是会引起线程间语义不一致。指令重排序的存在是因为流水线技术可以提高CPU的性能,而重排指令可以保证流水更顺畅。但是有些指令是不可以重排的,这也就是Happen-before规则。主要包括程序顺序规则(一个线程内语义一致),volatile规则(写先于读),线程中断(中断先于被中断)等等。


    Java并行的基础

    线程相关

       线程是轻量级进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。线程的状态包括:

    New:初始状态,当一个线程被创建时是这个状态。

    Runnable:初始态线程调用start方法后,线程会变成Runnable状态。

    Terminated:终止状态,当线程执行完毕之后进入此状态。

    Blocked:线程被阻塞时进入阻塞态。

    Waiting:无限期等待,runnable调用wait或sleep (不带参数)就会进入此状态。

    Timed_waiting:有限期等待,wait和sleep带参数。

    线程的方法

      start:调用start方法线程从初始态变为运行态,内部自动调用run方法。

      stop:直接终止线程,并且会立即释放锁,这样有可能破坏正在修改的对象,然后让别的线程读到这个被破坏的对象。

      interrupt:中断线程。

       join:等待线程执行完,主线程内调用a.join方法,即主线程要等a线程执行完。

       yield:当前线程让出CPU,但是有可能接下来仍然会获得CPU。

    volatile、synchronized 和JMM模型

        volatile关键字保证了变量的可见性和有序性。可见性通过每次线程修改变量后将变量值刷新到主内存中,每次读变量都从主内存中去读来保证。有序性通过禁止指令重排序保证。synchronized关键字则可以保证原子性、可见性和有序性。原子性通过加锁来实现。

    程序中并发可能引起的错误

    并发下的ArrayList:多线程下扩容可能会引起数组越界等问题。

    并发下的HashMap:扩容可能会导致死锁。

    错误的加锁:锁的对象要是同一个才有意义。

    JDK并发包

    同步控制

    可重入锁的优点:

    可以响应中断。也就是在等待锁的过程中,可以取消对锁的请求。

    锁申请等待超时:线程请求锁一段时间后没有获得锁就会放弃等待。

    公平锁:所有线程按照先后顺序依次执行,不会出现由于优先级导致的饥饿现象。

    ReadWriteLock:读写锁,适合读多写少的情况,读读不互斥,读写互斥,写写互斥。

    CountDownLatch:控制线程等待,通过一个计数器设置线程数。数值为0时主线程方能执行。

    CyclicBarrier:循环栅栏,计数器可以重复使用,当计数器完成一次计数时,所有线程一起执行。

    线程池

       为每一个任务创建一个线程执行,任务执行完成后销毁线程,当任务比较小并且数量比较多的时候系统开销会比较大,因此引入了线程池的概念。系统维护一定数量的线程,每当有新的任务进来时就从线程池中拿出空闲线程并执行任务,当没有空闲线程时会把任务放在任务队列中。

       线程池核心参数:

        corePoolSize:核心线程数量。

       maximumPoolSize:指定了线程池中的最大线程数量。

       keepAliveTime:线程数量大于核心线程数量后,多于的空闲线程的存活时间。

       unit:keepAliveTime的单位,秒分时等等。

      workQueue:任务队列,用于存储提交但是尚未被执行的任务。 

      handler:拒绝策略。包括1.直接抛出异常,阻止系统正常工作。2.默默的丢弃无法处理的任务。3.丢弃最老的请求,也就是任务队列中即将被执行的任务,然后尝试再次提交当前任务。4.直接在调用者线程里面运行当前被丢弃的任务,会影响系统性能。

    常见的工厂方法创建的线程池:

    newFixedThreadPool:设置一个核心线程数和最大线程数一样的线程池。当有一个新的任务提交时,若有空闲线程则执行之,否则的话把它放在任务队列中,任务队列满了就考虑拒绝策略了。

    newSingleThreadExecutor:返回一个只有一个线程的线程池。

    newCachedThreadPool:返回一个线程数目可变的线程池。

    并发容器简单介绍

    ConcurrentHashMap:一个并发的HashMap,线程安全。

    CopyOnWriteArrayList:适合读多写少的情况,底层是一个数组,适合高并发下读,当要修改数组是会复制一个数组并且替换原来的数组。

    ConcurrentLinkedQueue:高效的并发队列,底层使用链表实现。

    BlockingQueue:通过put和take方法来存取内容。

    SkipList:多层链表,链表中的数据是经过排序的。

    锁的优化及注意事项

    提高性能的方法

    减少持锁时间:也就是减少其他线程的等待时间。

    减少锁粒度:只在必要的地方加锁。

    读写分离锁:读多写少的情况下可以使用分离锁替代独占锁。

    锁粗化:将多个相邻的锁连在一起,减少线程不断请求、释放锁的时间。

    JVM层面的锁优化

    偏向锁:如果一个线程获取了锁,那么这个锁就进入偏向模式,每次线程请求时不用再做同步操作。

    轻量级锁:偏向锁存在竞争的情况下,锁就会膨胀为轻量级锁。

    自旋锁:当前线程暂时无法获得锁,会自旋几个时钟周期,若还没有获得锁,就挂起该线程。

    锁消除:利用逃逸分析技术,消除不可能存在资源共享的锁。节约请求锁的时间。

    无锁

     无锁假设对资源的请求是不会出现冲突的,因此不需要等待,所有线程都可以在不停顿的情况下持续执行。当遇到冲突时,使用CAS(比较并交换)的技术来鉴别冲突,一旦发生冲突,就一直重试一直到没有冲突为止。CAS的方法是这样的,包含三个参数,V代表要更新的变量,E代表要更新变量的预期值,N代表新值,当V和E相等时才可以使用N替换。

    AtomicInteger:无锁的安全整数,原子包下的类。

    AtomicReference:无锁的对象引用,可以对普通的对象引用进行包装。

    AtomicStampedeReference:带有时间戳的对象引用,通过保存状态信息可以解决对象两次更改之后值一样的情况。


    并行模式及并行算法

    单例模式

    保证对象全局唯一性的一种方式。

    不变模式

    一个对象一旦被创建,它的内部状态一定是不可以被改变的。使用final关键字。

    生产者消费者模式

    生产者线程用于提交用户请求,消费者线程用于处理用户请求,生产者和消费者之间通过共享缓冲区来进行通信。

    Future模式

     本质上属于异步调用。当一个线程实现了Callable接口并实现call方法时是可以返回真是数据的,future可以用于接受这个数值,并且通过get方法获得它。

    并行流水线

    将任务分成多个部分,可以充分利用多核CPU的优势。

    NIO

      通过selector将线程分发到多个channel上,每个channel对应着一个Buffer,从buffer中获得数据之后会通知selector,然后返回给线程。

    AIO

    异步非阻塞。异步意味这IO操作完成之后再给线程发送通知,非阻塞意味着各个线程之间完全不会相互影响。




    展开全文
  • 在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。 线程是轻量级的进程,是程序执行的...

    进程:进程是计算机汇总的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

    线程是轻量级的进程,是程序执行的最小单位。使用多线程而不是多进程去进行并发程序的设计,是因为线程间的切换和调度的成本远远小于进程。

    线程状态:

    线程的所有状态都在Thread中的State枚举中定义:如下:

    public enum State{

    NEW,

    RUNNABLE,

    BLOCKED,

    WAITING,

    TIMED_WATT\ING,

    TERMINATED;

    }

    NEW状态表示刚刚创建的线程,这种线程还没有开始执行。等到线程的start()方法调用时。才表示线程开始执行。当线程执行时,处于RUNNABLE状态,表示线程所需的一切资源都已经准备好了。如果线程在执行过程中遇到了synchronized同步快,就会进入BLOCKED阻塞状态,这时线程就会暂停执行,直到获得请求的锁。WATING和TIMED_WATING都表示等待状态,他们的区别是WATING会进入一个无时间限制的等待,TIMED_WATING会进行一个有时限的等待。

    展开全文
  • 七:对象和类 <br /> 可见性修饰符: public 使类,方法,数据域可以在任何类中访问 private使方法,数据域只能从自身所在的类中访问 不用以上两者的默认情况下,可以从同一个包的...

    七:对象和类


    可见性修饰符:

    public 使类,方法,数据域可以在任何类中访问

    private使方法,数据域只能从自身所在的类中访问

    不用以上两者的默认情况下,可以从同一个包的任何类中访问

    private可以防止数据被用户篡改,类更容易维护



    数据域封装:

    get方法:public 返回类型 get属性名(),如为布尔类型,public boolean is属性名()

     

    she方法:public void set属性名(数据类型 属性值)

     


    展开全文
  • JAVA核心技术读书笔记 第三章 JAVA的基本程序设计结构 数据类型、常量、运算符、数学函数、数值类型转换、关系和boolean运算符、位运算符、字符串、输入、循环、大数值、数组拷贝、数组排序、多维数组
  • 1.线程的状态 Thread join 方法 public class JoinMain {  public volatile static int i = 0;  public static class AddThread extends Thread{  @Override  public void run() {  /...
  • 《实战Java高并发程序设计读书笔记
  •  饥饿是在程序中的某个线程迟迟没能获取到推进所需要的资源,可能由于种种原因,优先级或者纯粹是概率问题,一般来说随着程序压力的下降饥饿的情况会很快得到缓解。  活锁发生在当线程进行资源谦让的时候,资源...
  • JAVA核心技术 卷Ⅰ 读书笔记-第二章 Java程序设计环境预备:相关专业术语2.1 安装Java开发工具包2.2 使用命令行工具 预备:相关专业术语 术语名 缩写 解释 Java Development Kit JDK Java...
  • JAVA核心技术 卷I 读书笔记-第一章1.1 Java程序设计平台1.2 Java“白皮书”关键术语1.3 Java applet 与 Internet1.4 Java发展简史1.5 Java的常见误解 1.1 Java程序设计平台 Java是一个完整的平台,有一个庞大的库...
  • 另一种用法 String substring(int start, int end)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 934
精华内容 373
关键字:

java程序设计读书笔记

java 订阅