Java Map《自己记录记忆》

来源:互联网 发布:淘宝服装图标 编辑:程序博客网 时间:2024/06/10 22:11

## java地图


如何解除死锁

最关键的是ServerSocketSocket的通讯

1: 绑定失败

2: 如何同步,就是SocketServerSocket进行通讯


1. 变量(定义,使用,赋值),关键字,表达式,流程控制,注释,函数定义  

楼主背景厚l(流程控制)z(注释)b(标识符(下美子,数,下划线,美元,字符,数字,前面三个可以是首字母的),变量(下美子数,最好不要用美元开头,因为美元开头有特殊的意义),表达式)j(关键字)h(函数定义)(厚因为有两个背景)

2. 基本数据类型,数值型,


//包装类,在Integer上面最大的作用就是进制的转换
//进制转换,数字转化为字符
System.out.println(Integer.toHexString(60));System.out.println(Integer.toOctalString(60));System.out.println(Integer.toBinaryString(60));
//字符转化为数字
System.out.println(Integer.parseInt("6c",16));


//自动装箱,下面的两个是相等的声明的,其实就相当于是java帮我们把127给自动封装了一层了
Integer cc = 127;Integer ccc = new Integer(127);
//一个数字如果在一个字节的范围内(-128127),如果之前定义过了,那么就用之前定义的那个,这个是不是有毛病呢?没毛病,因为如果bb修改了,那么bb使用的是新的地址了
Integer aa = 127;Integer bb = 127;System.out.println(aa==bb);
Integer x = 128;Integer y = 128;System.out.println(x==y);



3. 复合数据类型,包括数组(数组的申明),类和接口  

    反射, 枚举类型,范型(genericity),集合,String

      reg,cs,注册csmapAnotation

      reg,cs,ma 注册cs

      范型,只是在编译时起使用的,编译完之后的字节码文件中是没有范型的,例如ArrayList<String>就是范型的例子

      java 编程思想里面指出:一般的类和方法,只能使用具体的类型,要不就是基本数据类型要不就是自定义的类,如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的限制很大所以引入了范型了

      java 范型的核心概念,告诉编译器想使用什么类型,然后编译器帮你处理一切细节

      CSS(作用在Class上面,范型的S使用,S声明),MIMethod,interface,?,E

      3.1. 范型的定义(定义在类上面)和使用<T> T t  

      //如果使用范型的话,可以认为范型和Object相比范围一样,可以使用范型的地方都是可以使用Object的, 
//
好处1:范型的get的时候不用强制类型转换了,(get方法
//
好处2:类型不正确的问题,可以在编译的时候就发现,而不用等到运行的时候才能发现了(set方法)  
//
范型也只有在编译的时候有用,编译后字节码中是没有范型的 
//
就像是ArrayList<String> list = new ArrayList<>(); list.get(0)也是不用类型转换的;  

3.2.范型的定义在方法和静态方法上面 

3.3.范型定义在接口上面,实现的时候分为两种情况,已经指定了特定的类型和未指定特定的类型,已经指定了的,那么实现类可以省略掉这个<T>的声明,如果没有指定就是不能省略掉 

可以认为是继承和实现都是可以自己让继承和实现的类自己控制,自己想要定义范型就定义,如果自己不想那么就等到使用的时候

class ClassImplementInterfaceWithGenric<E> implements testInterfaceWithGenric<E>

class ClassImplementInterfaceWithGenricAndType implements testInterfaceWithGenric<Integer>

G<? extends Y> G<? extends X>的子类型(如List<? extends Cat> List<? extends Animal>的子类型)。

G<X> G<? extends X>的子类型(如List<Animal> List<? extends Animal>的子类型)

G<?> G<? extends Object>等同,如List<?>List<? extends Objext>等同。

 /**
 * 范型只在编译时期有用,编译完成后,就没有用了,所以按照这个逻辑的化,反编译是看不到这个String
 * <?>相当于是<? extends Object>其实就相当于是没有的,问问饿(我)哦,
 * <E><? extends E>的子类
 * 如果Z F的子类 <? extends Z><? extends F>
 * @param args
 */


http://www.linuxidc.com/Linux/2013-10/90928.htm 



Collectionsmap的遍历输出:

* 遍历:全体猜不上,瞎掰b,可vip,全部都有tcCollections,b遍历iterators数组,kekeysetentrysetvalues


遍历:全体猜不上,瞎掰b,可vip,全部都有tcCollections,b遍历iterators数组,kekeysetentrysetvalues

Collection

toString直接输出(例如:System.out.println(cishus);)

collection的遍历,toString直接输出,iterator,转数组遍历

list的遍历,toString直接输出,iterator,转数组遍历,可以通过下标,listiterator

set的遍历,toString直接输出,iterator,转数组遍历

map的遍历, toString直接输出,entrySet,keySet,values


Collection:


 *苍老师mvc collectionl lists setmmapv vector
*
钻石无或配不上,咋啊双人床无或配不上,挨扁不用初中生
* list
你(list)瞎掰,挨g人是sb,来了挨g人服了。
* set
,谁,嘿嘿等顺序,停车c大吼排嘘。

*祖籍排序大小(数组,集合),分祖籍图(for,数组,集合,map图),最后可变(可变参数,在最后)私人(static import

*
*
钻石无或配不上,咋啊双人床无或配不上,挨扁不用初中生
* c
钻石无或配不上,z增加addaddAlls删除,removeclear,无或没有获得,p判断isEmptyb遍历Iterators转数组
*
咋啊双人床无或配不上,遍历的时候不能够在遍历的里面使用collection进行增删,必须使用iterator进行
*
Iterator 遍历里面,不要用collection的对象进行增删,挨扁不用初中生,(ai Iterator,b遍历,不用,collection进行 zs删)
*
*

* list
你(list)瞎掰,挨锅人是sb,来了挨锅人服了。
* agrssb
瞎掰,挨锅人是sb。增删获更遍历都可以通过下标来的,ListIterator可以在里面直接进行遍历的时候进行addset
* List
是有顺序的,分为ArrayList(列表) LinkedList(链表)
* List
都是有下表的,增删获更遍历都可以通过下标来的。arsgsb阿仁是个sb
* ListIterator
可以在里面直接进行遍历的时候进行addset
* LinkedList
来了挨锅人服了。linkedlist来了,add挨,get锅,remove人,fisrt服,last
* list
里面判断是否包含的contains是通过equals 来判断的,如果是String就是内容,如果是对象就是地址,基本数据类型就是值
*
*
set,谁,嘿嘿,等顺序,停车c大吼排嘘。(c compareTo,comparator)
* HashSet,TreeSet
*
首先并不是都是要比较equals的方法的,
* hashset
首先比较的是hashcode,如果hashcode相等,那么在判断equals
* treeset
,比较的只有是compareTo,comparator,带有排序的功能,但是必须是相同的类,不然如果出现了StudentString,那么就不好辨识了。除非重写Studentcompareto方法
* compareTo
里面使用的是本地的减去被比较的,如果大于说明就是要排在被比较的后面,一般都是和前面的进行比较的,所以如果大于,那么输出的时候直接就是在后面了,如果将某一个类的compareTo设置为1那么后面添加的一定排在前面添加的后面
*
大吼排嘘,大的放在后面,treeset可以利用这点进行排嘘


祖籍排序大小(数组,集合),分祖籍图(for,数组,集合,map图),最后可变(可变参数,在最后)私人(static import
Arrays
工具类,Collections工具类,for,最后可变参数,静态导入,rumtimegc();

Arrays工具类,toList();可以将一个数组转化为listList.toArray可以将list转化为数组,需要注意的是这里的这个list.toArray(new String[list.size()])使用的很巧妙

Arrays还可以进行排序,最大值,最小值,需要注意的是,这里的排序是会直接修改list里面的顺序的

Collections,也可以进行排序,

Collections.sort(list),

Collections.sort(list,new comparator)

Collections.sort(list4,Collections.reverseOrder());

Collections.sort(list5,new CompareByLength().reversed());

Collections.max(list5,new CompareByLength())

for增强,可以作用于数组,listmap

可变参数,最后可变

静态导入,static import

运行时,Runtime

gc()


Map:

//pp,双人床,hg可是vip,盼空间值
//添加,putputAll
//双人床,s删除,r removec clear
//hg可是viph获取,g get,可k ekeySet,entrySet,s sizevip valuesß
//盼空间值,盼p判断,空isEmpty,键,containsKey,值containsValues





String:

1 /** 

2     * 影城流行不同不变,或判换换(获取,判断,转换(最重要),替换),尝滋味包拯(等)开涮复羯鸡,忍受兔兔吃素开包吉步 

3     影城流行不同不变。影城(y引号,常量c池),流行(new 新的)不同(equals == 不一样)不变(字符串常量,不能够改变) 

4     * 获取:长度,字符,位置,(尝滋味) 

5     判断:包拯(等),开刷(开始结束) 

6     * 转换:字符数组,字节数组,基本数据类型(一个是字符数组的意思,还有复也有两种的意思,静态方法和构造方法)羯(字节数组)鸡 

7     替换:忍受兔兔吃素,r replace subString,toUpCase toLowCase, trim(), compareTo,split 

8     * 从某个位置开始查找,注意这里的fromindex 是包含这个index 

9     开始的是包含的,结束的是不包含的,开包吉步 

10      */  

StringBuilder,增删改查反不安全。增加,删除,修改,查找获取,反转,但是是线程不安全的,但是效率高

//什么是编码,什么是解码,需要编码的内容就是固定不变的内容,例如我们要发电报出去,那么电报的内容就是需要编码的
//
简单的来说就是固定不变的就是需要编码的,根据不同的编码得到的内容就是编码后的内容



Annotation,(记忆:所以是@里面有一个a所以是annotation


 

3.4.通配符,通配符不用声明,范型需要申明  

3.5.范型限定 通配符?extends E(如果后面的E是范型的话,那么前面要声明,如果E是固定的例如String那么就是不用在前面声明的)

 

3.1 java特性:封装,继承,多态  

单身,对象激发抽象,接口,多态,内部类,私有(权限管理)(单身,对象激发口臭多,累不累?是哟)

单例模式:(手电筒)(s私有化构造函数,d单个对象,t提供方法)

对象初始化的过程:自己的宝贝乖乖的,结果感冒,(z,字节码文件,j,静态代码块,d,堆,b,成员变量,b,成员变量,g,构造代码块,g,构造函数,d,堆中的首地址给栈),静态代码块,构造代码块,构造函数,在main之前执行

继承拔火罐,那么就轻松减肥,变娃娃鱼魔鬼身材

继承:拔火罐,b成员变量,h成员函数(轻松减肥qsjf轻松减肥,q权限,s私有,j静态,f返回值)g构造方法(娃娃鱼魔,w父类无构造方法,w父类无参构造方法,y父类有参构造方法,m superthis

final:终级量贩表(final,类,方,变)

抽象类:(有沟不实可有方法继承?不能就fps,匿名。)(有构造,不能实例话,可有抽象方法,继承抽象类?不能和finalprivaestatic一起用,可以使用匿名内部类实现new

接口多方便

接口:(多方便,接口之间多继承,方法,方法是abstract的,变量,变量是final的)  

多态辣椒,偷点抱回家,吃货资质

多态:子类的实例赋值给父类的引用(猫是猫,猫是动物,动物不一定是猫),

辣椒(类的多态,接口的多态)偷点(特点)抱(成员变量)回(成员函数)家(静态函数),才是吃货(成员函数)资质(执行看子类)

结果感冒jggm:,静态代码块,构造代码块,构造函数,在main之前执行,静态代码块只执行一次,构造方法代码块可以用来同一个类的共性的内容的初始化,1jng

对象初始化的过程:

1:因为创建对象需要使用字节码文件,所以先加在字节码文件到方法区  z

2:如果有静态代码块,执行静态代码块  j (这里应该还有一个静态的变量赋默认值和初始值)  

**上面是静态部分的。** 

3: 在堆中开辟内存  d

4:为成员变量赋默认值  b

5:为成员变量赋初始值  b

6: 执行构造代码块  g  

7: 执行构造函数  g  

8:把对象在堆中的首地址付给栈中的引用  d

自己的宝贝乖乖的(z,字节码文件,j,静态代码块,d,堆,b,成员变量,b,成员变量,g,构造代码块,g,构造函数,d,堆中的首地址给栈)

这里一定要注意的是构造代码块执行前,变量已经赋了初值了  

单例模式一共三步(手电筒,水稻田)(s私有化构造函数,d单个对象,t提供方法)为了保证单例的单,那么就不能在外边去创建对象,私有化构造函数然后自己提供,但是提供了以后外边需要调用,那么因为不能创建对象,所以只能通过一个static的方法来获取(懒汉是还需要考虑同步的问题,要添加sychonized

继承,(拔火罐b成员变量,h成员函数,g构造函数)

成员变量,如果该变量是私有的,那么继承的类是不能直接访问的,需要通过方法去访问的,父类和子类可以有相同的名字的变量,通过superthis 来进行区别

成员函数(qsjf轻松减肥,q权限,s私有,j静态,f返回值),这里就是重写,重写的规则有4个:

1:子类重写的,权限必须要大于或者等于比父类的该方法的权限,

2:私有的方法不能够被重新,

3,静态的只能静态的,

4:参数必须一致,如果有返回值,那么返回值可以是父类的返回值类型或者返回值类型的子类

构造方法:(娃娃鱼魔)w父类无构造方法,w父类无参构造方法,y父类有参构造方法,m superthis 

1:父类没有构造方法,类如果有没有构造方法,系统回自动的给类一个无参的构造方法,类如果有了构造方法,系统就不会去自动的创建无参的构造方法了。子类如果没有构造方法,默认的就会创建一个无参的构造方法,而且该构造方法里面使用super()

2:父类有无参的构造方法,子类默认的就会在无参构造方法第一行使用父类的无参构造方法(也可以写出来super()

3:父类没有无参的构造方法有有参的构造方法,子类需要指定父类的构造方法,子类自定义的构造方法可以指定自己的构造方法(this()),但是此构造方法一定要继承父类的构造方法()

5:默认的,super()是默认的调用父类的空的构造方法,没有写的话,默认的就是super(),在第一行,如果调用了this()了,那么就不会调用super()

final可以用来修饰类,方法和变量(成员变量,对象,局部变量,对象),终级量贩表(final,类,方,变)

final修饰的类,不能被继承 

final修饰的方法不能被重写

final修饰的变量不能修改,如果是int那么就是常量

要记住的是 ***值传递,原来的值相当于是使用final修饰了,参数值可以随意修改

局部变量接收的值不能被改变了

如果是对象,那么指向的该对象不能被改变(但是对象里面的内容可以被修改,其实就是对象的地址不变但是内部可以修改)

例如Collections.sort()Arrays.sort()都是会对原来的listarray里面的进行改变的

抽象类:(有沟不实可有方法继承?不能就fps,匿名。)(有构造,不能实例话,可有抽象方法,继承抽象类?不能和finalprivaestatic一起用,可以使用匿名内部类实现new)(个人理解,这个主要是为了能够必须要重写一个方法的目的,就像古时候加入什么帮会,那么你必须要做某一件事情才能加入,才能算是一类人)模版设计模式就是使用的抽象类来完成的。模版设计模式:当实现一个功能时候,功能的一部分是确定的,另一部分是不确定的,确定过的部分还会用到不确定过的部分,那么就把不确定的部分暴露出去,让子类去实现


1:抽象类有构造方法,这个是为了子类对象的初始化,抽象类,一定是父类,和普通类的区别:(抽象类不能创建对象,抽象类可以含有抽象方法)

2:抽象类不能创建对象实例

3:抽象类可以含有抽象方法,也可以不含有抽象方法,如果希望一个类不能被创建对象时,可以把该类修饰为abstract的,就像接口也不一定含有方法一样,Seriable就是这样的标记接口。

4:继承了抽象类的子类,如果没有重写父类中的抽象方法,那么该类也含有抽象类

5: 方法里面不能和privatestaticfinal一起使用,因为abstract的是必须要继承的  

6:可以通过匿名内部类实现创建实例,其实应该算是匿名内部类实现了那个抽象类

接口:(多方便,接口之间多继承,方法,方法是abstract的,变量,变量是final的)interface,类的继承可以得到该继承体系的基本功能,通过实现接口可以得到继承体系外的额外的功能,

1:接口和接口直接按是继承的关系,接口之间的继承可以是多继承的。

2: 方法是abstract

3: 变量是final,不是static的就是不可修改的


多态:

子类的实例赋值给父类的引用(猫是猫,猫是动物,动物不一定是猫)

辣椒(类的多态,接口的多态)偷点(特点):抱(成员变量)回(成员函数)家(静态函数),才是吃货(成员函数)资质(执行看子类)

前提:当然是存在继承或实现  

多态的缺点:只能够使用父类定义的功能

多态的好处:提高了程序的扩展性,前期定义的功能可以背后期出现的事物使用

class 动物{},class extends动物{}

把猫堪称猫  mao = new 猫();

把猫看成动物动物 mao = new 猫();

但是不能把动物看成猫,猫 dong = new动物();

类多态,可以通过instanceof来判断是那一个子类的

接口多态,接口其实是特殊的类,所以也是类的多态的,子类的实例赋值给父类的引用

一定一定要注意这里不是重写是多态,

多态中成员的特点:抱(成员变量)回(成员函数)家(静态函数),才是吃货(成员函数)资质(执行看子类)

默认的都是编译和执行都看父类的,但是成员函数的执行是看子类的。(前提是子类重写了父类的方法,而不是说子类有这个方法,父类没有这个方法)成员变量:编译和执行都看父类,(抱)

成员函数:编译的时候看父类,执行的时候看子类,(回)

静态函数:编译和执行的时候都看父类,(加)




内部类:内部理发,收费,可部分参数里面括号匿名。

内部类,内部理发,(类l,方法f)收费(声明,访问),可bf分(b变量final,可),参数里面括号匿名

/**
 *
内部类,定义在类里面,定义在方法里面
 *
内部类嘛,内部人可以用的,
 */

 1: 内部类作用在类里面,和成员变量和成员方法是一个等级的,

 内部类的声明,两种,一种是普通的内部类(new Outer()).new Innter(),一种是静态的内部类 new Outer.Innter();如果内部类有静态方法,该内部类必须是静态的内部类

 2: 内部类调用外部类中的对象和成员,内部人员嘛,当然可以很方便的使用内部的变量和方法了  

 3: 内部类作用在方法里面,局部内部类(方法的参数上面和方法里面),若要使用方法内部的局部变量,该变量需要声明为final的,如果没有声明也是可以的,但是如果出现变量的修改就一定要是设置为final的。  

 4: 匿名内部类,(匿名信,所以没有真实的名字,都是代号)

 匿名内部类,匿名就是没有名字,内部类,就是内部类嘛,继承了某个类或者是实现了某个方法的类

 匿名内部类,属于内部类作用在方法里面的情况(方法的参数上面和方法里面)

 

 http://blog.csdn.net/rodulf/article/details/68958606 

 (首先一定一定要记得的是,首先它是内部类,不能说是直接new出来的,而是通过java自己创建了一个内部类来继承了某个类,创建的类的名字是java自己定的匿名的,所以所以说匿名内部类,首先是内部类,只不过是java自己给你创建了一个简单类名而已,所以才叫匿名啊。

 首先它是内部类,只是没有名字而已,所谓的匿名也就是这个意思的。其实相当于是直接应用,只是匿名而已,相当于系统实现了该接口活着是继承了该类给它一个名字而已

 为什么要匿名内部类呢?因为这个只使用一次或者说没有其他地方调用了,没有必要单独的去创建一个对象。

 更多的作用在接口的回调上面,也体现了多态,多态作用在接口上面,实现了该接口的类,)


/**
 *
 *
 * 私人房间院子内外,家人兄弟远亲近邻,3210.
 *                              private     默认(包访问权限)  protected(继承访问权限)  public
 * 1: 同一个类中                                                                    
 * 2: 同一个包中(有无继承类都一样) 不能                                                
 * 3: 不同的包中有继承关系          不能           不能                                   
 * 4: 不同的包中无继承关系          不能           不能          不能                       
 *
 * 这个和分遗产有点像:
 * 同一个类,说明是有类似父子的继承关系,或者是夫妻关系的,同一个包,相当于是一个大家庭的,有兄弟姐妹
 * 对于物品,分为了4个类型的:
 * 保险柜里面的,房内的,院子里面的,院子外面的
 * 私有的,默认的,保护的,公开的
 * 保险柜子里面的东西,只有我的继承人可以碰
 * 房内的东西,家人都可以碰
 * 院子里面的东西,不是本地的家人的,外地的亲戚也可以碰,
 * 院子外面的东西,所有的人都可以碰
 *
 * q1:顶级类的定义只能是public和默认的
 * 如果一个顶级类是private的那么该类是不能够访问的所以不行
 * 如果一个顶级类是protected的那么该类是不能够被别的包里面的进行继承的,也是不能够被访问的(说明3,是不同的包中,有继承关系的,这里都不可能去继承,哪里来的继承关系呢?所以不能够访问),所以这个相当于就是默认包权限了,所以就不要使用protected
 * 类,只可以使用默认的和public来修饰
 *
 * q2: 还有挎包去访问的时候为什么不能够访问:就是因为被访问的类不是public
 *
 * q3:什么时候使用protected
 * protected
 * 一般情况下为了实现纯粹的封装用的就是private,而使用protected可以封装也可以继承
 * 一个比较典型的例子,不知道你学没学过Android开发(用java的)
 * 一个界面类需要继承Activity类,重写其中onCreate(),onPause(),onDestroy()等方法,这些方法就是protected的,这是为了继承同时也避免直接调用从而混乱应用的执行顺序
 * @param args
 *
 */

 



 

4.  UI,很简单就是有点像Androidui的里面,非常相似

5. 语言中的异常

报错分为两种:记住那张图,就是书上的那张图

都是继承自Throwable的类的,(我们的友盟统计,获得到的就是就是errorruntimeexception

Error, Exception

然后Exception分为RuntimeException和非RuntimeException, 

(RuntimeException,运行时异常,我们的友盟统计的,例如NullPonitException,OutofIndexException),

//Java认为如果遇到运行时异常,就应该中断,而不应该去处理

//阿里巴巴的开发文档中,第一个就是:1.不要捕获 Java类库中定义的继承自 RuntimeException的运行时异常类 

当我们手动的将 RuntimeException进行throw的时候,例如下面的,我们在使用该方法的时候,不用去try catch,在引用的方法那里也不用进行throws

public static int divWithRuntimeException(int a, int b){
    if(b==0)
        throw new ArithmeticException("除数为0");
    return a/b;
}

RuntimeException,例如FileNotFoundException 

有点房子,如果有问题那么我们就要爆出来,就是throw

验房子,相当于编译,这个时候我们会看看房子有没有什么大体上面的问题,例如墙体脱落阿,灯不亮啊,这些问题throw出来了,那么装修公司就要去修复这个问题。但是有很多问题,例如房屋个隔音不好啊,这些问题不是在验房子的时候就会知道的,这些问题是在使用的时候才有的

使用房子的时候,例如房屋隔音不好的问题,只有在使用的时候才知道,这个就是RuntimeException

还有房子可能有的时候,某一个地区就是突然断电了,那么这个是我们解决不了的,就是Error


还有需要注意的是,在类上面我们使用的是throws Exception,而如果是方法里面使用的是throw new Exception();注意后者是没有s

在方法上面是throws,抛出异常是使用throw

//Java认为如果遇到运行时异常,就应该中断,而不应该去处理


异常的输出,可以通过PrintStream:

PrintStream printStream = new PrintStream("error.txt");
try{
    int i = 50 / 0;
}catch (Exception e){
    e.printStackTrace(printStream);
}finally {
    printStream.close();
}



6.   io

字节流和字符流,字符流主要就是为了处理字符的,所以这里面可以设置字符编码

6.1 字节流,接口:InputStream,OutputStream,

文件,过滤,管道,对象(还有一个在网络部分常用到的就是Byte  FFPOB

`ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int read;
while ((read = inputStream.read(bytes))!=-1){
    //System.out.println(new String(bytes));
    byteArrayOutputStream.write(bytes,0,read);
}

//就使用"UTF-8"既可以了
String jsonString = byteArrayOutputStream.toString("UTF-8");

`

FileInputStream,FileOutputStream

BufferedInputStream,BufferedOutputStream

PipeInputStream,PipeOutputStream

ObjectInputStream,ObjectOutputStream. (readObject,writeObject)

对象的序列化,序列化只会包含类的成员变量,不能包含,**可以理解为放在堆中的都是可以进行序列化的,其他的例如放在栈中的方法,以及放在常量池中的都是不可以序列化的**

6.2 转换流, InputStreamReader,OutputStreamWriter

字符流, BufferredReader,BufferredWriter,FileWriter,FileReader, PrinterWriter(可以直接输出一行)

三福新品,piapia,鹿死谁手,

3File,creatNewFile,propertiespropertiesSystem.propertieslsssloadstoresetProperty,stringPropertyNames

File:有三种构造方法:

File dir = new File("hello/newFile");
File file = new File(dir,"dir.txt");
File file1 = new File("/Users/kodulf/Documents/volepackage/ReviewDay12/hello/newFile/","dir2.txt");

如果文件不存在,那么需要使用file.creatNewFile来进行新的文件的创建。

File在获取某个目录里面的文件列表的时候可以进行过滤

FileFilter fileFilter = new FileFilter() {
    @Override
    public boolean accept(File pathname) {
        boolean ret = false;
        if (pathname.getName().endsWith(".java")||pathname.isDirectory())
            ret = true;
        return ret;
    }
};
File[] files = file.listFiles(fileFilter);

/**

piapia,鹿死谁手,
 * 测试properties,最终这个properties其实还是一个map,所以map的所有的都是可以使用的,只是自己封装了几个方法
 * piapia,鹿死谁手,
 * propertiesSystem.propertieslsssloadstoresetProperty,stringPropertyNames
 * 展示可以使用list
 * 导入load,可以是普通的,也可以是xml格式的
 * 导出可以是xml格式的,也可以是普通的文本的格式的,store,storeToXML
 * 设置就是setProperties
 * 遍历可以使用stringPropertyNames可以获取到这个属性的名字的集合,
 * 系统的properities
 */




7. 线程  ,有点像汽车,汽车就是有启动,堵车,停车,等待红绿灯等状态

别忘了线程池

线程的状态

线程的创建

ssa

然后是启动start(),结束(stop,interrupted,),检查(isAlive),挂起(sleep/yield,suspend/resume,join

线程的启动,start();

线程的调度,可以设置优先级,yield()强制终止线程的执行,可以给其他同等优先级线程一个运行机会,类似sleep()

线程的基本控制:结束,检查,挂起,stop(不推荐了)/isAlive(),/sleep,suspend,resume,join()


isAlive()的方法意味着这个线程正在执行,而只说明这个线程已被启动,并且既没有运行stop(),也尚未运行完方法run()


sleep()

通常,线程不是休眠期满后就立刻被唤醒,因为此时其他线程可能正在执行,重新调度只在下面的几种情况下发生:

被唤醒的线程具有更高的优先级

正在执行的线程因为其他与原因被堵塞

程序处于支持时间片的系统中

大多数情况下,后两种条件不会立刻发生


RUNNABLE的状态,此时的线程已经启动,处于线程的run()方法中,这种情况下线程可能正在运行,也可能没有运行,只要cpu一空闲,马上就会运行,可以运行但并没在云心的线程都排在一个队列中,这个队列陈伟就绪队列。

Thread创建的构造方法中可以设置线程的名字Thread()


ThreadGroup threadGroup = new ThreadGroup("group ooo");

Thread thread = new Thread(threadGroup, new Runnable() {
    @Override
    public void run() {
        int i = 100;
        while (i>0){
            i--;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Thread thread1 = Thread.currentThread();
            String name = thread1.getName();
            String groupName = thread1.getThreadGroup().getName();
            System.out.println("groupName="+groupName+"  name="+name);
        }
    }
},"thread hahaha");
thread.start();


如果考虑例如售票,每人都售50张票,和4个人一起售50张票是不同的

线程创建的两种方法里面:

1: 继承Thread

2: 实现runnable的接口

####  4个人每人50张票:

1: Ticket extends Thread{

int num = 50;

..

}


Ticket ticket1 = new Ticket();

Ticket ticket2 = new Ticket();

Ticket ticket3 = new Ticket();

Ticket ticket4 = new Ticket();


2: Ticket implements Runnable{

int num = 50;

Ticket ticket1 = new Ticket();

Ticket ticket2 = new Ticket();

Ticket ticket3 = new Ticket();

Ticket ticket4 = new Ticket();


Thread thread1 = new Thread(t1);

Thread thread2 = new Thread(t2);

Thread thread3 = new Thread(t3);

Thread thread4 = new Thread(t4);


}


#### 一共40张票

1: Ticket extends Thread{

//使用静态的就可以了

static int num = 50;

..

}


Ticket ticket1 = new Ticket();

Ticket ticket2 = new Ticket();

Ticket ticket3 = new Ticket();

Ticket ticket4 = new Ticket();


2: Ticket implements Runnable{

int num = 50;

Ticket ticket1 = new Ticket();

Thread thread1 = new Thread(t1);

Thread thread2 = new Thread(t1);

Thread thread3 = new Thread(t1);

Thread thread4 = new Thread(t1);


}


#### 一起买票50张的时候,如果任务里面有超过多一条的代码,那么很有可能会出现错票的情况,

为了演示错票的情况,可以将输出的代码复制20

这个是因为当不是同步的时候,例如thread1可能执行到了第11行了,这个时候cputhread2抢过去了,那么此刻thread1就会进入就绪队列,等到thread1又得到cpu的时候num已经变了  

解决办法是使用



#### 函数同步锁和静态函数同步锁

演示可以生命一个类,里面有两个方法,

一个方法是sychonizedstatic的,public static void add(int i){里面是很多的输出}

另一个方法

public void reduce(int i) {    synchronized (ClassWithStaticSync.class) {里面是很多的输出}}

这个时候两个方法其实使用的是同一把锁,


演示,可以生命两个Thread


    public static void testStaticSync(){
        ClassWithStaticSync classWithStaticSync = new ClassWithStaticSync();

        StaticThread staticThread = new StaticThread(classWithStaticSync);
        NoStaticThread noStaticThread = new NoStaticThread(classWithStaticSync);

        staticThread.start();
        noStaticThread.start();

    }


}


class StaticThread extends Thread{
    ClassWithStaticSync classWithStaticSync;
    public StaticThread(){

    }
    public StaticThread(ClassWithStaticSync classWithStaticSync){
        super();
        this.classWithStaticSync = classWithStaticSync;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            classWithStaticSync.add(i);
        }
    }

class NoStaticThread extends Thread{
    ClassWithStaticSync classWithStaticSync;
    public NoStaticThread(ClassWithStaticSync classWithStaticSync){
        super();
        this.classWithStaticSync = classWithStaticSync;
    }
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            classWithStaticSync.reduce(i);
        }
    }
}

#### 死锁,两个进程都获取了对方的锁

public class DeadLockClass {

    public static synchronized void add(){

        System.out.println("first class add"+ Thread.currentThread().getName());

        DeadLockSecondClass.reduce2();

    }

    public static synchronized void add2(){
        System.out.println("first class add 2"+ Thread.currentThread().getName());

    }
}


public class DeadLockSecondClass {
    public static synchronized void reduce(){
        System.out.println("second class add"+ Thread.currentThread().getName());
        DeadLockClass.add2();

    }

    public static synchronized void reduce2(){

        System.out.println("second class add"+ Thread.currentThread().getName());
        DeadLockClass.add2();

    }

}


public static void testDeadLock(){
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 300; i++) {
                DeadLockClass.add();
            }

        }
    });

    Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 300; i++) {
                DeadLockSecondClass.reduce();
            }

        }
    });

    thread1.start();
    thread2.start();
}



#### 同步方法里面如果有sleep,那么它是不会让出cpu的,测试一下


public class SyncWithSleepInit {

    public static synchronized void add(){

        System.out.println("before sleep "+Thread.currentThread().getName()+" p"+Thread.currentThread().getPriority());
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after sleep "+Thread.currentThread().getName()+" p"+Thread.currentThread().getPriority());
        System.out.println("add "+Thread.currentThread().getName()+" p"+Thread.currentThread().getPriority());

    }
}


public static void testSyncWithSleep(){
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 200; i++) {
                SyncWithSleepInit.add();
            }
        }
    });

    Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 200; i++) {
                SyncWithSleepInit.add();
            }
        }
    });

    thread2.setPriority(Thread.MAX_PRIORITY);
    thread1.start();
    thread2.start();

}


### 单例模式里面懒汉式的安全问题

如果没有使用同步的synchonized来修饰方法,那么会出现,例如三个进程一起去调用了new的方法了,解决办法就是使用synchonized


package review.bank;

/**
 * Created by zhangyinshan on 2017/2/26.
 */
public class SingleInstanceLazyMan {

    private SingleInstanceLazyMan(){

    }

    static SingleInstanceLazyMan singleInstanceLazyMan ;

    //synchronized 如果不添加,那么会出现三个进程一起调度的情况
    public static synchronized SingleInstanceLazyMan getInstance(){
        if(singleInstanceLazyMan==null){
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());
            System.out.println("before new "+Thread.currentThread().getName());

            singleInstanceLazyMan = new SingleInstanceLazyMan();

            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());
            System.out.println("after new "+Thread.currentThread().getName());

        }

        return singleInstanceLazyMan;
    }

}



public static  void testSingleInstance(){
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            SingleInstanceLazyMan.getInstance();
        }
    });

    Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            SingleInstanceLazyMan.getInstance();
        }
    });
    Thread thread3 = new Thread(new Runnable() {
        @Override
        public void run() {
            SingleInstanceLazyMan.getInstance();
        }
    });

    thread1.start();
    thread2.start();
    thread3.start();
}




# 卖错票,锁睡觉懒汉,别比比(一个人的时候别比比,在一个生产者一个消费者时候不要用while,多个生产者多个消费者的时候用while),独自等待,通知他人,列车到拉萨了 


#### 卖票的两种形式,

#### 错票的发生,

#### 函数同步锁和静态函数同步锁,只要知道锁是不同的就可以,演示就是两个thread,一个调用static的,一个调用行数同步锁(两种情况,一种是this,一种是类的.class(也就是static的锁))

#### 锁里面有睡觉的情况,

#### 懒汉式的并发使用同步

#### 别比比(不要用while),独自等待,通知他人(一个产品,多个产品,一个生产者一个消费者,多个生产者多个消费者)所谓的独自等待,就是wait方法是将自己放到等待列表中,通知他人,就是notify是通知在等待列表中的其他的线程来执行(如果不使用wait方法,那么就需要用一个while的循环不停的去判断了,就像是客人不停的去问老板,饭好了没有啊,饭好了没有啊,你烦不烦?哈哈)

#### 列车到拉萨了 l c列车,lockconditionla lock.lock condition.await(),s condition.signal lock.unlock


### 进程间通讯,(独自等待,通知他人)使用waitnotify 主要是为了对资源访问的时候的有序的进行,不然就会出现例如取资源的取到了负数的,生产的超过了需求的,就像是餐馆里面的炒菜和客人点餐,如果没有按照waitnotify来,那么可能会出现无序的情况,客户应该拿到菜的,但是却拿到了空的盘子,因为厨师还没有炒好菜,厨子炒出来的才应该可以出来的,但是盘子不够了,例如盘子只能够5个人的,但是厨子炒出了第6盘,那么就没有地方放了。


## 如果不使用wait方法,那么就需要用一个while的循环不停的去判断了,就像是客人不停的去问老板,饭好了没有啊,饭好了没有啊,你烦不烦?哈哈

#### 一个生产者,一个消费者,一个产品


这个时候只需要使用boolean来判断,然后使用notifywait来控制生产和消费的数据

package review.bank;

/**
 * Created by zhangyinshan on 2017/2/26.
 */
public class Resource {

    /**

     * isSetting当为true的时候是进行设置
     */
    boolean isProducting;
    String name;

    public synchronized void set(String name){
        //当当前不是设置的时候,那么wait,等待
        if(!isProducting){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.name = name;
        System.out.println("生产了 "+name);
        isProducting = false;
        notify();
    }

    public synchronized void printOut(){
        if(isProducting){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //执行到下面说明isProducting已经设置为了false
        if(name!=null)
        System.out.println("消费了:"+name);
        isProducting = true;
        notify();
    }

}



#### 一个生产者,一个消费者,多个产品

这个时候产品需要使用一个数组来演示,设置一个当前生产库里面的产品的位置,

然后判断就是判断当前的产品的位置,如果是已经达到了最大值了,那么生产的要自己等待,如果产品已经没有了,那么消费要自己等待,

package review.bank;

/**
 * Created by zhangyinshan on 2017/2/26.
 */
public class MoreProduct {

    /**

     * 指向生产的库里面的当前的位置的
     */
    int currentPosition=-1;
    final int totalNum = 50;
    String[] pro;

    public MoreProduct(){
        pro = new String[totalNum];
    }

    /*
*
     * 为什么使用waitnotify就是防止出现取空的情况和,生产超过了需求了
     */
    public synchronized void product() {
        //当当前的位置超过4了,说明生产已经超过了需求了
        if (currentPosition >=(totalNum-1)){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        currentPosition++;
        System.out.println("生产了 "+currentPosition+" "+Thread.currentThread().getName());
        notify();
    }

    public synchronized void consume(){
        //当当前的位置在-1的时候
        if(currentPosition<=-1){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("消费了"+currentPosition+" "+Thread.currentThread().getName());
        currentPosition--;
        notify();
    }

}



#### 多个生产者,多个消费者:使用notifyAll同时多添加一层判断

package review.bank;

import review.ThreadTest;

/**
 * Created by zhangyinshan on 2017/2/26.
 */
public class MoreProductorMoreConsumer {

    final int totalNum = 50;
    String[] products;
    /**

     * 当前生产的位置
     */
    int currentPosition;


    public MoreProductorMoreConsumer(){
        products = new String[totalNum];
    }


    /*
*
     * 之前只有一个生产者,一个消费者的时候notify的话就是通知到对方,而现在如果是多个生产者,多个消费者,
     * 那么notify也会通知到和自己一样的,例如生产者通知了生产者
     *
     */
    public synchronized void product(){
        if(currentPosition>=(totalNum-1)){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //这里还要再添加一次判断,因为通知执行的时候,可能正好3个生产者都收到了notifyAll了,都来执行了,因为之前的currentPosition可能是48
        // 那么就会出现495051
        if(currentPosition<=totalNum) {
            currentPosition++;
            System.out.println("生产了 " + currentPosition + " " + Thread.currentThread().getName());
        }
        notifyAll();
    }


    public synchronized void consume(){
        if(currentPosition<=-1){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //这里必须要添加一层判断,因为通知执行的时候,可能正好3个消费者都收到了notifyAll了,都来执行了,因为之前的currentPosition可能是0
        //那么就会出现-1-2-3
        if(currentPosition>=0) {
            System.out.println("消费了 " + currentPosition + " " + Thread.currentThread().getName());
            currentPosition--;
        }
        notifyAll();
    }


}



## 如何解决死锁的问题





### 如果操作共享数据的代码只有一行也没有同步的问题





线程的结构,虚拟cpu,执行的代码和处理的数据

线程的状态有四种:其实是六种状态,看下面的thread的枚举,新建,可运行,堵塞和死亡

死亡的条件只有两种:一个是执行完了,一个是stop()

sleep()suspend的区别,应该是sleep会将cpu让出来吧,suspend不会?

由运行状态切换为堵塞的状态有四种途径:sleepwaitsuspend,和io流堵塞

有堵塞会到可运行的状态是:resume()和notifynotifyAll()

中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序。虽然初次看来它可能显得简单,但是,你必须进行一些预警以实现期望的结果。你最好还是牢记以下的几点告诫。 


    首先,忘掉Thread.stop方法。虽然它确实停止了一个正在运行的线程,然而,这种方法是不安全也是不受提倡的,这意味着,在未来的Java版本中,它将不复存在。 

thread.stop();不安全,已经过时了
thread.interrupt();安全的,推荐的


/**
 * A thread state.  A thread can be in one of the following states:
 * <ul>
 * <li>{@link #NEW}<br>
 *     A thread that has not yet started is in this state.
 *     </li>
 * <li>{@link #RUNNABLE}<br>
 *     A thread executing in the Java virtual machine is in this state.
 *     </li>
 * <li>{@link #BLOCKED}<br>
 *     A thread that is blocked waiting for a monitor lock
 *     is in this state.
 *     </li>
 * <li>{@link #WAITING}<br>
 *     A thread that is waiting indefinitely for another thread to
 *     perform a particular action is in this state.
 *     </li>
 * <li>{@link #TIMED_WAITING}<br>
 *     A thread that is waiting for another thread to perform an action
 *     for up to a specified waiting time is in this state.
 *     </li>
 * <li>{@link #TERMINATED}<br>
 *     A thread that has exited is in this state.
 *     </li>
 * </ul>
 *
 * <p>
 * A thread can be in only one state at a given point in time.
 * These states are virtual machine states which do not reflect
 * any operating system thread states.
 *
 * @since   1.5
 * @see #getState
 */
public enum State {
    /**

     * Thread state for a thread which has not yet started.
    
*/
    NEW,

    /**

     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
    
*/
    RUNNABLE,

    /**

     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
    
*/
    BLOCKED,

    /**

     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
    
*
     * <p>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * is waiting for a specified thread to terminate.
     */
    WAITING,

    /**

     * Thread state for a waiting thread with a specified waiting time.
     * A thread is in the timed waiting state due to calling one of
     * the following methods with a specified positive waiting time:
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
    
*/
    TIMED_WAITING,

    /*
*
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;
}


一个线程阻塞的原因是多种多样的,可能是因为执行了Thread.sleep(),可能是因为需要等待一个较慢的外部设备,例如磁盘和用户,所有呗阻塞的线程按次序排列,组成一个阻塞队列,

8.  网络  


TCP/IP5层协议:  

应用层:URL(网络通讯的三要素:协议+ip地址+端口号,正好就是组成了URL,URLConnection,HttpURLConnection  

传输层:TCP:  Socket,ServerSocket(注意这里是服务器端Socket的简称,ServerSocket), UDP:DatagramPacker,DatagramSocket,MulicastSocket  

网络层(IPInetAddress  (用于标识网络上面的硬件资源)使用的不多

链路层:  

物理层:  


URL Uniform Resource Locator统一资源定位器  

我们也是可以直接通过浏览球来打开我们本地的文件的:一定要注意的是这里的file后面如果是linux的系统,后面一定要有根目录的/

file:///users/zhangyinshan/Documents/temp/device-2017-02-17-151053.png

URL的构造方法可以有四种:

URL(String spec)

URL(URL url,String spec)(方便一个目录下面多个文件)

URL(String protocol, String host, String file)

URL(String protocol, String host, int port,String file)(方便不同的协议)

注意url获取最后的文件名是没有直接的方法的,需要我们手动的去写的, url.getFile();获取到完整的路径,然后使用split去切分,得到最后一个就好了


get请求和post请求的例子要熟练

注意HttpURLConnection是继承了URLConnection的,可以进行一些更多的设置例如请求的方法是post



试试喊催乳服务,十餐内堵(不复发)反(时间参数内容,读写返回)

sshcrServiceContext,Service,HttpUtils,RequestCallback,Result/ResultList

ServiceContext,是通过它来获取Service

Service 是将httputils进行了封装后特定的服务service

HttpUtils(时间参数内容,读写返回)

首先设置时间还有postget的方法,

然后设置我们提交的参数,如果是get是明显的,将参数直接放在路径上面,如果是post,那么就是会放在body里面的,

内容,我们需要设置Content-Typeapplication/x-www-form-urlencoded,Content-Lenght,

读写,设置这个是允许读写的

返回,返回的结果通过json转化为Result或者是ResultList

RequestCallback

onFailure(T t, Exception e),

onResponse(T t)

Result<T>/ResultList<T>





通讯:  

|ServerSocket | | Socket|

| :--: | :--: | :--: |

|ServerSocket||Socket|

|accept()||open()|

|inputStream|<--通讯-->|outputStream|

|outputStream|<--通讯-->|InputStream|

|close()||close()|  


ServerSocket 可以设置连接的数量:例如2个:new ServerSocket(10888,2);


现在可以实现 ServerSocket使用while 循环在哪里等待,然后Socket 去发送请求,但是

我的疑问就是这个ServerSocket 是需要一只在那边等着吗?

最关键的是ServerSocketSocket的通讯

注意socket,如果没有关闭output,那么收的那一端会不停过的等待接收,socket.shutdownOutput();


1: 绑定失败

2: 如何同步,就是SocketServerSocket进行通讯,



都市地皮慎入,都市地皮安排代售

(甩卖)(甩甩甩)刷刷刷,刷啊,哎哦,客官(关闭输入输入流),,啥安排,哦爱,客官



/**
 * (甩卖)(甩甩甩)刷刷刷,刷啊,哎哦,客官(关闭输入输入流)
 * @throws IOException
 */
private static void testTCPServer() throws IOException {
    ServerSocket socket =null;
    Socket accept = null;
    try{

        socket = new ServerSocket(29999);
        accept = socket.accept();

        System.out.println("连接成功");
        InputStream inputStream = accept.getInputStream();
        byte[] bytes = new byte[1024];

        int read = inputStream.read(bytes);
        System.out.println(new String(bytes,0,read));
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        if (socket != null) {
            socket.close();
            accept.close();
        }
    }
}



/**
 * 啥安排,哦爱,客官
 * @throws IOException
 */
public static void testTCPClient() throws IOException {
    Socket socket =null;
    try{
        socket = new Socket(InetAddress.getLocalHost(),29999);
        OutputStream outputStream = socket.getOutputStream();

        outputStream.write("hello world".getBytes());

    }catch (Exception e){
        e.printStackTrace();
    }finally {
        socket.close();
    }
}



/**
 * 服务器端,都市地皮慎入,
 */
public static void test() throws SocketException {
    DatagramSocket datagramSocket = null;
    try {
        datagramSocket = new DatagramSocket(29999);
        byte[] bytes = new byte[1024 * 1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);

        datagramSocket.receive(datagramPacket);

        System.out.println(datagramPacket.getAddress());
        System.out.println(datagramPacket.getSocketAddress());

        byte[] data = datagramPacket.getData();
        System.out.println(new String(data,0,datagramPacket.getLength()));

    }catch (Exception e){
        e.printStackTrace();
    }finally {
        if (datagramSocket != null) {
            datagramSocket.close();
        }
    }
}

/**
     * 客户端:都市地皮安排待售
     * @throws SocketException
     */
    private static void test() throws SocketException {
        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket();
            byte[] bytes = "hello wrold".getBytes();
            DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),29999);
//          也可以使用下面的进行设置
//            DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);
//            datagramPacket.setAddress(InetAddress.getLocalHost());
//            datagramPacket.setPort(29999);

            datagramSocket.send(datagramPacket);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (datagramSocket!=null){
                datagramSocket.close();
            }
        }

    }








import java.util.Date;
import java.util.concurrent.
*;

/**

 * Created by Kodulf on 2017/4/11.
 
*/
public class ThreadPoolTest {

    public static void main(String[] args){

        Test test1 = new Test("1");
        Test test2 = new Test("2");
        Test test3 = new Test("3");
        Test test4 = new Test("4");
        Test test5 = new Test("5");
        Test test6 = new Test("6");
        Test test7 = new Test("7");
        Test test8 = new Test("8");
        Test test9 = new Test("9");

        /**

        
*
         *
         *


        
线程池的优点:简单的来说就是节省资源
         1
:就像是洗澡,如果每一个人都是在自己家里面洗澡,那么每个人都需要开太阳能,都需要热水,例如如果是1000个人,那么就是需要消耗1000*每个人的资源,1000*1度电,=1000度电
        
但是如果大家一起去浴室洗澡,有一个大池子,那么可以有很多人一起洗澡,这个时候需要消耗的资源其实还是一直都是那么多,
        
例如这个浴室每天的耗电量是800度,那么如果数量是1000个,那么就会节省200度电,如果数量是2000,那么可能会比800度多一点例如1000度,但是也会比2000度电少很


        
首先需要注意的是
        
例如上面的Test是继承了Thread的线程,它并没有使用.start去启动,而是使用的executorService.execute(test1);
        
所以test1只是一个任务,真正执行的是是线程池里面的线程。

        
鲜仁澡堂,草莓口味好,散芬草香,
        
鲜仁澡堂,x线程,r,任务,澡堂节省资源
        
草莓口味好,cmkwhcorePoolSize, maximumPoolsize,keepAliveTime,workQueue,handle
        
散芬草香,sfcnewSingleThreadExecutor();newFixedThreadPool(int i);newCachedThreadPool();newScheduleThreadPool();
        
联系上面来说,newSingleThreadExecutor任务之间没有任何联系,

         * Creates a new {@code ThreadPoolExecutor} with the given initial
         * parameters and default thread factory and rejected execution handler.
         * It may be more convenient to use one of the {@link Executors} factory
         * methods instead of this general purpose constructor.
         *
         * @param corePoolSize the number of threads to keep in the pool, even
         *                      if they are idle, unless {@code allowCoreThreadTimeOut} is set
         *                     
保存在池中的线程的数量,即使这些线程他们已经idle空闲了,除非设置了allowCoreThreadTimeOut
         *                     
需要的核心员工多少人,即使他们没有事情做也是会让他们在那边的。
         *
         * @param maximumPoolSize the maximum number of threads to allow in the pool
         *
         *                       
线程池中最大允许的线程的数量
         *                       
最大允许的员工的数量
         * @param keepAliveTime when the number of threads is greater than
         *                      the core, this is the maximum time that excess idle threads
         *                      will wait for new tasks before terminating.
         *                     
千万要记住:默认的,这个保持活动的政策只有在线程的数量超过了核心线程的数量的时候才起作用,但是如果方法allowCoreThreadTimeOut(boolean)可以被用来设置这个time-out的政策给核心的线程
         *                     
简单的来说,其实就是,如果当前的员工数量超过了我核心的员工的数量,如果你多长时间不干活了就把你辞职了,但是需要注意的是这里的worker,其实是线程池中的线程,并不是被执行的任务
         *                     
当线程的数量大于核心线程的数量的时候,这个keepAlivetime就是超出的idle的线程最多保存多少时间了
         *
         * @param unit the time unit for the {@code keepAliveTime} argument
         * @param workQueue the queue to use for holding tasks before they are
         *                  executed.  This queue will hold only the {@code Runnable}
         *                  tasks submitted by the {@code execute} method.
         *                 
这个queue是用来在任务被执行前hold这个任务的,这个queue只有在任务是被execute方法提交的时候才会调用的
         *                  queue
其实就相当于是需要处理的事情,像是银行里面就是等待办理业务的人,像是工厂里等待处理的元件,公司待处理的文件
         *
         * @param handler the handler to use when execution is blocked
         *                because the thread bounds and queue capacities are reached
         *                 
处理当这个因为thread的边界或者是queuecapacities达到了最大值了executionblocked
         *               
有四中hanlder的政策被提供:
         *                    1
:在默认的ThreadPoolExecutor.AbortPolicy,这个handlerreject的时候抛出一个运行时的RejectedExecutionException的异常
         *                    2
:在ThreadPoolExecutor.CallerRunsPolicy,这个thread触发execute本身去运行这个task
         *                         
这提供了一个简单的反馈控制机制,将减慢新任务提交的速度。
         *                    3
:在ThreadPoolExecutor.DiscardPolicy,一个任务如果不能够被运行,那么就会被简单的丢弃了
         *                    4
:在ThreadPoolExecutor.DiscardOldestPolicy,如果executor没有被关闭,在这个work queue最上面的的任务将会被丢弃,其实就是最旧未使用的,然后这个execution将会回退
         *                     
(这个可以又失败,调用另一次重复)
         * @throws IllegalArgumentException if one of the following holds:<br>
         *         {@code corePoolSize < 0}<br>
         *         {@code keepAliveTime < 0}<br>
         *         {@code maximumPoolSize <= 0}<br>
         *         {@code maximumPoolSize < corePoolSize}
         * @throws NullPointerException if {@code workQueue} is null
         */




        //
得到一个只有一个线程的线程池的对象,任务是顺序被执行的,执行完过一个任务再执行下一个任务
        // alive-time out
0秒钟,默认的,这个保持活动的政策只有在线程的数量超过了核心线程的数量的时候才起作用,而这了核心线程数量和最大线程数量是一样的所以这里不会起作用的
        //
注意后面的是LinkedBlockingQueue<Runnable>就是一个无边界的queue,可以添加任意数量的任务,但是需要注意的是这些任务之间不要有任何的联系
        //ExecutorService executorService = Executors.newSingleThreadExecutor();
        //Executors.newFixedThreadPool
调用的是new Executors.FinalizableDelegatedExecutorService(
        // new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));


        //
得到一个有固定的线程数的线程对象,任务数量和线程数量相同时,任务被同时执行,任务数量大于线程数量时
        //
多出来的任务会等待已经创建的线程空闲时被执行,(其实就是上一个任务执行了,线程就可以执行其他的任务了)
        //
核心线程和线程的最大数量是一样的,
        // alive-time out
0秒钟,默认的,这个保持活动的政策只有在线程的数量超过了核心线程的数量的时候才起作用,而这了核心线程数量和最大线程数量是一样的所以这里不会起作用的
        //
使用的是LinkedBlockingQueue<Runnable>,就是一个无边界的queue,可以添加任意数量的任务,但是需要注意的是这些任务之间不要有任何的联系
        //
注意fixed的翻译是限定的意思
        // ExecutorService executorService = Executors.newFixedThreadPool(2);
        //return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());



        //
创建缓冲的线程池对象,自身会创建一定数量的线程,当线程数量大于任务数量是,会自动的销毁空闲的线程
        //
当任务数量增加时,会增加线程的数量
        //
核心线程数为0,最大线程数量为Integer.MAX_VALUE,大概是20亿左右的,相当于是无限大的线程数量了,
        //
等待的时间是60秒钟,就是1分钟,这个是每一个线程在idel的时候都会等待1分钟,然后自动的销毁的
        //
注意这里的queueSynchronousQueue是同步的queue,这些被执行的任务之间内部是有联系的才会使用这个SynchronousQueue
        //ExecutorService executorService = Executors.newCachedThreadPool();
        //new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());



        //
创建数量无限的线程池对象,空闲的线程也不会被销毁
        //
核心数量为设置的核心的数量,最大的线程数量是Integer.MAX_VALUE,相当于是无限的
        // keep-alive
的只是0 NANOSECONDS,这个
        //ExecutorService executorService = Executors.newScheduledThreadPool(3);
        //super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new ScheduledThreadPoolExecutor.DelayedWorkQueue());

       // ThreadPoolExecutor executorService = new ThreadPoolExecutor(2,2,10L,TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.AbortPolicy());

        /**

        
这个ThreadPoolExecutor实现了 AbstractExecutorServiceAbstractExecutorService实现了接口 ExecutorService;
         class ThreadPoolExecutor implements AbstractExecutorService
         class AbstractExecutorService implements ExecutorService
        
*/





        /*
*

         http://docs.oracle.com/javase/8/docs/api/

        
一个ExecutorService会可能会使用线程池中的多个线程中的一个去执行每一个被提交的task
        
默认的使用Executors的工厂类的方法去创建配置。
        
线程池解决了两个不同的问题:
        
他们常常能够改进性能当执行大的数量的异步任务的时候,通过减少每个任务的开销。
        
并且他们提供了一个绑定和管理资源,包括线程threads,还有在执行一个集合的任务的时候消耗的资源
        
每一个ThreadPoolExecutor同时强化了一些基本的数据统计,例如已经完成的任务数量

         An ExecutorService that executes each submitted task using one of possibly several pooled threads,
         normally configured using Executors factory methods.
         Thread pools address two different problems:
         they usually provide improved performance when executing large numbers of asynchronous tasks,due to reduced per-task invocation overhead,
         and they provide a means of bounding and managing the resources, including threads, consumed when executing a collection of tasks.
         Each ThreadPoolExecutor also maintains some basic statistics, such as the number of completed tasks.

        
为了能够在广泛的上下文中使用,这个类提供了需要可修改的参数和可扩展的。
        
然后,开发者还是强烈的建议使用一些方便的Executors工厂类方法,例如Executors.newCachedThreadPool(没有边界的线程池,)
         Executors.newFixedThreadPool(int)
(固定的长度的线程池),Executors.newSingleThreadExecutor()(单个)
        
常用的场景里面就可以使用这些配置好了前期的工厂方法。或者是使用下面的guide去手动的配置

         To be useful across a wide range of contexts, this class provides many adjustable parameters and extensibility hooks.
         However, programmers are urged to use the more convenient Executors factory methods Executors.newCachedThreadPool()
         (unbounded thread pool, with automatic thread reclamation), Executors.newFixedThreadPool(int) (fixed size thread pool)
         and Executors.newSingleThreadExecutor() (single background thread),
         that preconfigure settings for the most common usage scenarios.
         Otherwise, use the following guide when manually configuring and tuning this class:

         
核心和最大的池子
         Core and maximum pool sizes
        
一个线程池会自动的适应池子的长度,根据设置的corePoolSize(核心池的size)和maximumPoolSize(最大的池子的size
        
当一个新的task(或者说是new的新的thread)放到execute(Runnable)里面执行的时候
        
如果这个时候线程池里面的线程的数量小于核心池的数量的时候,那么会在线程池里面新建一个新的thread去处理请求,即使线程池里面其他的正在工作的线程已经是idle的状态了
        
如果这个时候线程池里面的线程的数量大于核心池的数量但是小于最大线程池的数量的时候,除非queue已经满了才会去创建一个新的thread
        
通过设置核心线程池的数量和最大线程池的数量相等,那么你创建了一个固定大小的线程池
        
通过设置最大的线程池为一个无限的值,例如Integer.MAX_VALUE,你允许线程池去适应任意数量的concurrent task
        
大多数的情况,核心的线程池的数量和最大线程池的数量是在创建的时候设置的,也是可以通过方法setCorePoolSize(int) setMaximumPoolSize(int)去修改的。
         A ThreadPoolExecutor will automatically adjust the pool size (see getPoolSize())
         according to the bounds set by corePoolSize (see getCorePoolSize()) and maximumPoolSize (see getMaximumPoolSize()).
         When a new task is submitted in method execute(Runnable), and fewer than corePoolSize threads are running,
         a new thread is created to handle the request, even if other worker threads are idle.
         If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
         By setting corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool.
         By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool
         to accommodate an arbitrary number of concurrent tasks.
         Most typically, core and maximum pool sizes are set only upon construction,
         but they may also be changed dynamically using setCorePoolSize(int) and setMaximumPoolSize(int).


        
按需的构造方法
        
默认的情况,即使核心的threads只有在新的task到达了才会被初始化创建并且启动,
        
但是这个可以通过使用prestartCoreThread() prestartAllCoreThreads()两个方法来进行手动的重写。
        
如果你构造的线程池有一个非空的queue,你可能想要预启动threads

         On-demand construction
         By default, even core threads are initially created and started only when new tasks arrive,
         but this can be overridden dynamically using method prestartCoreThread() or prestartAllCoreThreads().
         You probably want to prestart threads if you construct the pool with a non-empty queue.


        
创建新的threads
        
通过ThreadFactory可以去创建新的threads。如果没有特殊的情况,一个Executors.defaultThreadFactory()会被使用,
        
它将会一相同的ThreadGroup和相同的NORM_PRIORITYnon-daemon的状态去创建threads
        
通过提供不同的ThreadFactory,你可以修改thread的名字,threadgroupprioritydaemon状态等等
        
如果ThreadFactory没有成功的去创建一个thread,这个时候返回的是null
        
这个executor执行者会继续,但是可能不能够执行任何task
        
线程应该拥有"modifyThread"修改thread的运行时的权限
        
如果worker threads或者其他的正在使用线程池的线程threads没有拥有这个运行时权限,
        
那么service可能会被降级,配置的修改可能不能够即时的起作用,
        
并且一个关闭的线程池可能在一个状态,这个状态终结是可能的,但是并没有完成



         Creating new threads
         New threads are created using a ThreadFactory. If not otherwise specified, a Executors.defaultThreadFactory() is used,
         that creates threads to all be in the same ThreadGroup and with the same NORM_PRIORITY priority and non-daemon status.
         By supplying a different ThreadFactory, you can alter the thread's name, thread group, priority, daemon status, etc.
         If a ThreadFactory fails to create a thread when asked by returning null from newThread,
         the executor will continue, but might not be able to execute any tasks.
         Threads should possess the "modifyThread" RuntimePermission.
         If worker threads or other threads using the pool do not possess this permission,
         service may be degraded: configuration changes may not take effect in a timely manner,
         and a shutdown pool may remain in a state in which termination is possible but not completed.


        
保持活动的时间,(如果你多长时间没有事情做了,那么我就要把你开除了)
        
如果线程池当前有笔核心线程数量多的线程,超出的线程如果已经是idle并且超过了keepAliveTime的时间了,那么将会被终结
        
这个提供了一个方法在线程池不是被激活使用的时候减少资源消耗。
        
如果线程池变成更加活跃以后,新的threads会被构造出来。
        
这个参数可以通过setKeepAliveTime(long, TimeUnit)手动的修改
        
使用Long.MAX_VALUE() TimeUnit.NANOSECONDS(纳秒)的值有效的将空闲的threads在终结之前关闭,就是说不可能被关闭的
        
默认的,这个保持活动的政策只有在线程的数量超过了核心线程的数量的时候才起作用
        
但是如果方法allowCoreThreadTimeOut(boolean)可以被用来设置这个time-out的政策给核心的线程,

         Keep-alive times
         If the pool currently has more than corePoolSize threads,
         excess threads will be terminated if they have been idle for more than the keepAliveTime (see getKeepAliveTime(TimeUnit)).
         This provides a means of reducing resource consumption when the pool is not being actively used.
         If the pool becomes more active later, new threads will be constructed.
         This parameter can also be changed dynamically using method setKeepAliveTime(long, TimeUnit).
         Using a value of Long.MAX_VALUE TimeUnit.NANOSECONDS effectively disables idle threads from ever terminating prior to shut down.
         By default, the keep-alive policy applies only when there are more than corePoolSize threads.
         But method allowCoreThreadTimeOut(boolean) can be used to apply this time-out policy to core threads as well,
         so long as the keepAliveTime value is non-zero.



        
队列
        
任何的BlockingQueue可能会被用于传送和持有提交的任务.
        
这个queue的使用需要和线程池的size一起,
        
如果少于核心线程池数量的线程正在执行,那么Executor经常更愿意添加一个新的thread而不是从queue中获取
        
如果是大于等于这个核心线程池的数量的时候,那么Executor进场会愿意将这个请求放在queue中,而不是添加一个新的thread
        
如果一个请求不能够被添加到queue中,那么一个新的thread将会被创建,除非是这个会超出了最大的线程数量,在这种情况下,这个任务会被rejected

        
洗面有三种常见的queue的场景:
         1
Direct handoffs(直接切换)
        
work queue的一个好的默认的选择是异步的queue (SynchronousQueue) 它会将tasks传递给threads而不是直接持有他们
        
这样,一个想要假如queuetask如果当前没有可以运行的thread,那么将会失败。所以呢,一个新的thread将会被创建
        
这个policy避免了当处理很多的内部有联系的请求的死锁,
        
直接奇幻通常需要没有设置最大的线程数量去避免reject新的提交的task

         2
Unbounded queues.无边界的queue
        
使用额一个为绑定的queue(例如LinkedBlockingQueue,这里面没有定义capcity
        
当核心新城池中的线程达到了数量了,并且正在运行busy的时候,需要将新的taskqueue中进行等待
        
也即是说,没有大于核心线程数量的线程还是会百创建(这个最大的线程数不会再起作用了)
        
这个在每一个线程都是独立的时候比较适合,所以任务不会影响其他的任务的执行。
        
例如,一个网页的server。当这个类型的queue可以有效的平滑的处理瞬间的突发的请求,
        
它允许unbounded work queue有不断的进行正在的可能心,当命令的平均到达速度比他们可以处理的快

         3
Bounded queues.有边界的queue
        
一个有边界的queue(例如一个ArrayBlockingQueue,可以通过设置有限的最大的线程池的数量来帮助避免资源疲惫,但是会比较难的去管理和控制
         queue
size的大小和最大池的长度可能会相互交易:
        
使用很大的queue和很小的线程池最小cpu使用,os资源,和上下文切换的开销,
        
但是会导致人为低吞吐量。如果任务常常block(例如如果他们i/o绑定)
        
系统可能会去schedule计划时间给更多的threads比你允许的多。使用小的queue通常运去大的线程池的size
        
这个会让cpus更娇繁忙,但是会遇到不可接受的计划开销,这个也会降低吞吐量


         Queuing

         Any BlockingQueue may be used to transfer and hold submitted tasks.
         The use of this queue interacts with pool sizing:
         If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
         If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
         If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.

         There are three general strategies for queuing:

         1
Direct handoffs. A good default choice for a work queue is a SynchronousQueue that hands off tasks to threads without otherwise holding them.
         Here, an attempt to queue a task will fail if no threads are immediately available to run it, so a new thread will be constructed.
         This policy avoids lockups when handling sets of requests that might have internal dependencies.
         Direct handoffs generally require unbounded maximumPoolSizes to avoid rejection of new submitted tasks.
         This in turn admits the possibility of unbounded thread growth when commands continue to arrive on average faster than they can be processed.

         2
Unbounded queues.
         Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity)
         will cause new tasks to wait in the queue when all corePoolSize threads are busy.
         Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.)
         This may be appropriate when each task is completely independent of others, so tasks cannot affect each others execution;
         for example, in a web page server. While this style of queuing can be useful in smoothing out transient bursts of requests,
         it admits the possibility of unbounded work queue growth when commands continue to arrive on average faster than they can be processed.

         3
Bounded queues.
         A bounded queue (for example, an ArrayBlockingQueue) helps prevent resource exhaustion when used with finite maximumPoolSizes,
         but can be more difficult to tune and control.
         Queue sizes and maximum pool sizes may be traded off for each other:
         Using large queues and small pools minimizes CPU usage, OS resources, and context-switching overhead,
         but can lead to artificially low throughput. If tasks frequently block (for example if they are I/O bound),
         a system may be able to schedule time for more threads than you otherwise allow. Use of small queues generally requires larger pool sizes,
         which keeps CPUs busier but may encounter unacceptable scheduling overhead, which also decreases throughput.



        
被拒绝的tasks
        
通过executeRunnable)来提交的新的任务在Executor被关闭了的时候,会被reject
        
同时如果Executor使用有限的范围给最大的线程数量和queue的容量,并且饱和了时候,也会被reject
        
不管是上面的两种方法中的哪一种,execute执行方法会触发 RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor)方法里面的 RejectedExecutionHandle
        
有四中hanlder的政策被提供:
         1
:在默认的ThreadPoolExecutor.AbortPolicy,这个handlerreject的时候抛出一个运行时的RejectedExecutionException的异常
         2
:在ThreadPoolExecutor.CallerRunsPolicy,这个thread触发execute本身去运行这个task
           
这提供了一个简单的反馈控制机制,将减慢新任务提交的速度。
         3
:在ThreadPoolExecutor.DiscardPolicy,一个任务如果不能够被运行,那么就会被简单的丢弃了
         4
:在ThreadPoolExecutor.DiscardOldestPolicy,如果executor没有被关闭,在这个work queue最上面的的任务将会被丢弃,其实就是最旧未使用的,然后这个execution将会回退
           
(这个可以又失败,调用另一次重复)

        
有可能去定义和使用其他RejectedExecutionHandler类型的类,
        
做这些需要一些仔细,特别是policy已经被设置好了去在特定的capcityqueuing policies
         Rejected tasks
         New tasks submitted in method execute(Runnable) will be rejected when the Executor has been shut down,
         and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated.
         In either case, the execute method invokes the RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor)
         method of its RejectedExecutionHandler.
         Four predefined handler policies are provided:
         1
In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection.
         2
In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task.
            This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.
         3
In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.
         4
In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down,
         the task at the head of the work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.)

         It is possible to define and use other kinds of RejectedExecutionHandler classes.
         Doing so requires some care especially when policies are designed to work only under particular capacity or queuing policies.



        
挂钩方法
        
这个类提供了可以冲洗饿的beforeExecuteafterExecute的方法,他们在执行任务之前和执行executiontask之后会被执行。
        
这些可以被操纵执行的环境,(其实就是进行一些环境的配置)
        
例如,重新初始化ThreadLocals,集合一些统计,或者是添加log的入口
        
还有,方法terminated()也可以被重写去执行一些特殊的processing这个process需要在Executor全部结束后执行的

        
如果hook或者回调方法抛出了异常,内部的worker threads可能会变成fail或者突然结束

         Hook methods
         This class provides protected overridable beforeExecute(Thread, Runnable) and afterExecute(Runnable, Throwable)
         methods that are called before and after execution of each task.
         These can be used to manipulate the execution environment;
         for example, reinitializing ThreadLocals, gathering statistics, or adding log entries.
         Additionally, method terminated() can be overridden to perform any special processing that needs to be done once the Executor has fully terminated.

         If hook or callback methods throw exceptions, internal worker threads may in turn fail and abruptly terminate.



         queue
巩固
        
方法getQueue()允许访问当前的queue为了监控和debug的方便。
        
使用这个方法为了任何目的都是强烈不建议的。
        
两个提供了的方法,removeRunnable)和purge()可以被用来在大量的queue的任务变成cancell的时候帮助存储回收

         Queue maintenance
         Method getQueue() allows access to the work queue for purposes of monitoring and debugging.
         Use of this method for any other purpose is strongly discouraged.
         Two supplied methods, remove(Runnable) and purge() are available to assist in storage reclamation when large numbers of queued tasks become cancelled.


        
定型
        
一个线程池如果不再在任何program中被提及并且没有任何的线程在执行将会被自动的shutdown
        
如果你想要去保证未被提及的pools被回收即使用户忘了调用shutdown(),
        
那么你必须安排那些不再使用的threads最后die,通过设置合理的keep-alive times,给0个核心线程池设置一个lower的边界或者设置FallowCoreThreadTimeOut(boolean)

         Finalization
         A pool that is no longer referenced in a program AND has no remaining threads will be shutdown automatically.
         If you would like to ensure that unreferenced pools are reclaimed even if users forget to call shutdown(),
         then you must arrange that unused threads eventually die, by setting appropriate keep-alive times,
         using a lower bound of zero core threads and/or setting allowCoreThreadTimeOut(boolean).


        
扩展的例子:
        
大多数的扩展会重写一个或者多个protectedhook方法。
        
例如下面的添加了一个子类,它又pauseresume的特征

         Extension example.
         Most extensions of this class override one or more of the protected hook methods.
         For example, here is a subclass that adds a simple pause/resume feature:


         class PausableThreadPoolExecutor extends ThreadPoolExecutor {
         private boolean isPaused;
         private ReentrantLock pauseLock = new ReentrantLock();
         private Condition unpaused = pauseLock.newCondition();

         public PausableThreadPoolExecutor(...) { super(...); }

         protected void beforeExecute(Thread t, Runnable r) {
         super.beforeExecute(t, r);
         pauseLock.lock();
         try {
         while (isPaused) unpaused.await();
         } catch (InterruptedException ie) {
         t.interrupt();
         } finally {
         pauseLock.unlock();
         }
         }

         public void pause() {
         pauseLock.lock();
         try {
         isPaused = true;
         } finally {
         pauseLock.unlock();
         }
         }

         public void resume() {
         pauseLock.lock();
         try {
         isPaused = false;
         unpaused.signalAll();
         } finally {
         pauseLock.unlock();
         }
         }
         }

        
还可以再看一下这个博客:http://www.cnblogs.com/exe19/p/5359885.html

         */

        //ExecutorService executorService = Executors.newSingleThreadExecutor();//
执行的最慢

        ExecutorService executorService = Executors.newFixedThreadPool(10);//
根据这个size的不同,越小执行的越慢,越大执行的越快

        //ExecutorService executorService = Executors.newCachedThreadPool();//
执行的最快,同时执行完1分钟之后,就会关闭这个线程池了,可以看它的方法如下就指导了
        //ExecutorService executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());//
执行的最快
        Date date = new Date();
        executorService.execute(test1);
        executorService.execute(test2);
        executorService.execute(test3);
        executorService.execute(test4);
        executorService.execute(test5);
        executorService.execute(test6);
        executorService.execute(test7);
        executorService.execute(test8);
        executorService.execute(test9);



        //
需要自己手动的去关闭,如果自己不手动的关闭,它是不会自己关闭的
        //executorService.shutdown();


        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("
当前executorService.isShutdown"+executorService.isShutdown()+" executorService.isTerminated"+executorService.isTerminated());

                }
                //System.exit(0);
            }
        }).start();


    }



    static class Test extends Thread{
        String id;
        Test(String id){
            this.id = id;
        }
        @Override
        public void run() {
                int num = 100;
                if (id.equals("2")) {
                    num = 122;
                }
                for (int i = 0; i < num; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "  ---" + id + "--- " + i);

                }


        }

    }



}




   






0 0