Java SE 5 新特性

来源:互联网 发布:馒头日记 知乎 编辑:程序博客网 时间:2024/05/19 06:38

本文转载自:http://www.cnblogs.com/taven/archive/2011/12/18/2291877.html


JDK5.0新特性系列---1.自动装箱和拆箱 


/** * 基本类型的数据值可以直接赋给基本数据对象,基本数据的对象也可以直接赋给基本数据变量 * 在表达式中,基本类型的数据值可以和基本数据对象进行运算 * 基本数据类型的数组不能实现自动装箱和拆箱,即int[]不能当成Integer[]使用 *//** * 演示基本数据类型的自动拆箱和装箱 */public class AutoBox {       /**整数类型的自动拆箱和装箱*/       public static void intAutoBox(){              //可以装基本数字类型赋给数字对象              //在J2SE之前,必须用iObj = new Integer(200);              int i = 100;              Integer iObj = 200; //将200装箱              System.out.println("开始时: i = " + i + "; iObj = " + iObj);                           //将数字对象赋给基本数字类型              //在J2SE5.0之前,必须使用i = tempObj.intValue();              Integer tempObj = iObj;              iObj = i;              i = tempObj;  //将对象拆封              System.out.println("将i与iObj的值互换后: " + "i = " + i + "; iObj = " + iObj);                           //在表达式内可以自动拆箱和装箱              iObj += i + tempObj;              i *= iObj + tempObj;              System.out.println("i = " + i +"; iObj = " + iObj);       }             /**boolean类型的自动拆箱与装箱*/       public static void booleanAutoBox(){              boolean b = false;              Boolean bObj = true; //装箱              if(bObj){//拆箱                     System.out.println("bObj = " + true);              }              if(b || bObj){                     b = bObj; //拆箱                     System.out.println("bObj = " + bObj +"; b = " + b);              }       }             /**字符类型的自动拆箱与装箱*/       public static void charAutoBox(){              char ch = 'A';              Character chObj = 'B';              System.out.println("ch = " + ch + "; chObj = " + chObj);              if(ch != chObj){ //拆箱                     ch = chObj; //拆箱                     System.out.println("ch = " + ch + "; chObj = " + chObj);              }       }             public static void main(String[] args){              intAutoBox();              booleanAutoBox();              charAutoBox();              //注意,支持基本数据类型的自动拆箱和装箱,但是不支持基本类型数组的自动拆箱和装箱              int[] is = {12,34,56};              //Integer[] iObj = is; //error!!!                    }} 



JDK5.0新特性系列---2.新的for循环

import java.util.ArrayList;import java.util.List; /** * 新的for循环,格式为for(type x:type y) * 表示遍历数组或集合y的元素,把元素值赋给x */public class ForEach {       /**对整数数组求和*/       public static long getSum(int[] nums) throws Exception{              if(nums == null)                     throw new Exception("错误的参数输入,不能为null!");              long sum = 0;              //依次取得nums元素的值并累加              for(int x : nums){                     sum += x;              }              return sum;       }       /**对整数列表求和*/       public  static long getSum(List<Integer> nums) throws Exception{              if(nums == null)                     throw new Exception("错误的参数输入,不能为null!");              long sum = 0;              //可以与遍历数组一样的方式遍历列表              for(int x:nums){                     sum += x;              }              return sum;       }       /**求多维数组的平均值*/       public static int getAvg(int[][] nums) throws Exception{              if(nums == null)                     throw new Exception("错误的参数输入,不能为null!");              long sum = 0;              long size = 0;              //对于二维数组,每个数组元素都是一维数组              for(int[] x : nums){                     //一维数组中的元素才是数字                     for(int y : x){                            sum += y;                            size ++;                     }              }              return (int)(sum/size);       }             public static void main(String[] args)throws Exception{              int[] nums = {456,23,-739,163,390};              List<Integer> list_I = new ArrayList<Integer>();              for(int i = 0; i < 5; i++){                     list_I.add(nums[i]);              }              System.out.println(getSum(nums));              System.out.println(getSum(list_I));              int[][] numss = {{1,2,3},{4,5,6},{7,8,9,10}};              System.out.println(getAvg(numss));       }}   



JDK5.0新特性系列---3.枚举类型

/** *enum关键字表示枚举类型,它的作用相当于类声明中的class关键字 *枚举类型不能有public的构造方法 *所有的枚举值都是public、static、final的,这些修饰符都是自动加上,无须程序员手动添加 *枚举值之间用逗号","分开,最后一个枚举值后面接分号";" *每一个枚举值是一个枚举类型的实例 *可以在枚举类型中定义非枚举值变量,这些变量可以使用任何修饰符 *变量和方法的定义必须在枚举值后面定义*/public class EnumType {       /**人Person的枚举类型*/       enum Person{              CHINESE,    //中国人              AMERICAN,   //美国人              ENGLISH;    //英国人       }       public static void main(String[] args){              System.out.println("Person枚举值的数目: " + Person.values().length);              //遍历枚举类型中的所有值              System.out.println("Person枚举值如下: ");              Person[] ps = Person.values();   //values()方法返回Person类型的数组              for (Person p : ps){                     System.out.print(p + " ");   //toString()方法返回枚举值的名称,此处打印CHINESE AMERICAN ENGLISH              }              System.out.println();              Person p = Person.CHINESE;              //比较枚举值              if(p == Person.CHINESE){                     System.out.println("p' value equals Person.CHINESE");              }              //使用valueOf获得字符串描述的枚举值              p = Person.valueOf("AMERICAN");              //在switch中使用枚举值              //switch中可以放置的类型有byte,short,int,char,enum,注意没有long               switch(p){              case CHINESE:                     System.out.println("p is Chinese");                     break;              case AMERICAN:                     System.out.println("p is American");                     break;              case ENGLISH:                     System.out.println("p is English");                     break;              }              //获得枚举值在枚举类型中声明的顺序              System.out.println("AMERICAN的序号: " + Person.AMERICAN.ordinal());              System.out.println("CHINESE的序号: " + Person.CHINESE.ordinal());              System.out.println("ENGLISH的序号: " + Person.ENGLISH.ordinal());                           //使用更复杂的枚举类型ComplexPerson              ComplexPerson cp = ComplexPerson.CHINESE;              //因为为CHINESE枚举值覆盖了toString()方法,所以调用的是CHINESE的toString方法              System.out.println("cp.toString(): " + cp);              cp = ComplexPerson.AMERICAN;              //因为没有为AMERICAN枚举值覆盖toString方法,所以调用默认的toSting方法              cp = ComplexPerson.OTHER;              System.out.println("cp.getValue(): " + cp.getValue());       }       /**一个更复杂的枚举类型*/       enum ComplexPerson{              //枚举值              //CHINESE的value属性为"中国人"              CHINESE("中国人"){                      public String toString(){                            return "这是个中国人";                     }              },              AMERICAN("美国 人"),              ENGLISH("英国人"){                     public String toString(){                            return "这是个英国佬";                     }              },              OTHER{                     public String toString(){                            return "这是个其它国家的人";                     }              };              private String value = null; //枚举类值的value属性,只能声明在枚举值的后面              //默认的构造方法              ComplexPerson(){                     value = "其他人";              }              //带参数的构造方法              ComplexPerson(String value){                     this.value = value;              }              //获取value属性               public String getValue(){                     return this.value;              }       }} 



JDK5.0新特性系列---4.静态导入

/** *静态导入:是指可以import类的静态方法和静态变量,在使用时,无须指定类名, *         便可以使用这些被import的静态方法和静态变量,这就是静态导入 *写import语句时,可以定位到一个静态方法或静态变量(以前是定位到类) *可以使用通配符(*)代表导入该类的所有静态方法和静态变量 *不允许静态方法和静态变量出现重名的情况*/import static java.lang.Math.max;  //导入了Math的max方法import static java.lang.Math.min;  //导入了Math的min方法import static java.lang.Integer.*; //导入了Integer的所有静态方法和静态属性public class StaticImport {       public static void main(String[] args){              //通过静态导入使用Math的静态方法              System.out.println(max(5,10));              System.out.println(min(5,10));              //通过静态导入使用Integer的静态方法              System.out.println(parseInt("55544555"));              System.out.println(toBinaryString(2354));              //通过静态导入使用Integer的静态属性              System.out.println(MAX_VALUE);              System.out.println(MIN_VALUE);       }}



JDK5.0新特性系列---5.可变长参数Varargs

/** * 在J2SE5.0之前,当传入到方法的参数个数不固定时,经常采用数组的方式传递参数 * 在J2SE5.0之后,可以使用可变长参数的我给方法传递参数 *//** * 在参数类型和参数名之间使用"..."(三个英文的点),表示该参数为可变长的 * 通过新的for循环读取可变长参数中的值 * 一个方法里最多只能有一个变长参数,而且这个变长参数一定要放在参数表的最后一个参数*/import static java.lang.System.*;public class VarArgs {       public static void print(Integer... s){              for(int s2:s){    //解封                     out.print(s2+"/t");              }              out.println();       }       public static void main(String... args) {              print();           //调用public static void print()方法              print(1);          //调用public static void print(Integer i)方法  封箱              print(2,3);        //调用public static void print(Integer... s)方法 封箱              print(4,5,6);      //调用public static void print(Integer... s)方法 封箱       }} 



JDK5.0新特性系列---6.格式化输出

import java.util.Date; /** * 使用printf输出 *//**关键技术点 * 使用java.io.PrintStream的printf方法实现C风格的输出 * printf 方法的第一个参数为输出的格式,第二个参数是可变长的,表示待输出的数据对象 */public class Printf {        public static void main(String[] args) {              /*** 输出字符串 ***/              // %s表示输出字符串,也就是将后面的字符串替换模式中的%s              System.out.printf("%s", new Integer(1212));              // %n表示换行              System.out.printf("%s%n", "end line");              // 还可以支持多个参数              System.out.printf("%s = %s%n", "Name", "Zhangsan");              // %S将字符串以大写形式输出              System.out.printf("%S = %s%n", "Name", "Zhangsan");              // 支持多个参数时,可以在%s之间插入变量编号,1$表示第一个字符串,3$表示第3个字符串              System.out.printf("%1$s = %3$s %2$s%n", "Name", "san", "Zhang");                           /*** 输出boolean类型 ***/              System.out.printf("true = %b; false = ", true);              System.out.printf("%b%n", false);               /*** 输出整数类型***/              Integer iObj = 342;              // %d表示将整数格式化为10进制整数              System.out.printf("%d; %d; %d%n", -500, 2343L, iObj);              // %o表示将整数格式化为8进制整数              System.out.printf("%o; %o; %o%n", -500, 2343L, iObj);              // %x表示将整数格式化为16进制整数              System.out.printf("%x; %x; %x%n", -500, 2343L, iObj);              // %X表示将整数格式化为16进制整数,并且字母变成大写形式              System.out.printf("%X; %X; %X%n", -500, 2343L, iObj);                           /*** 输出浮点类型***/              Double dObj = 45.6d;              // %e表示以科学技术法输出浮点数              System.out.printf("%e; %e; %e%n", -756.403f, 7464.232641d, dObj);              // %E表示以科学技术法输出浮点数,并且为大写形式                          System.out.printf("%E; %E; %E%n", -756.403f, 7464.232641d, dObj);              // %f表示以十进制格式化输出浮点数              System.out.printf("%f; %f; %f%n", -756.403f, 7464.232641d, dObj);              // 还可以限制小数点后的位数              System.out.printf("%.1f; %.3f; %f%n", -756.403f, 7464.232641d, dObj);                           /*** 输出日期类型***/              // %t表示格式化日期时间类型,%T是时间日期的大写形式,在%t之后用特定的字母表示不同的输出格式              Date date = new Date();              long dataL = date.getTime();              // 格式化年月日              // %t之后用y表示输出日期的年份(2位数的年,如99)              // %t之后用m表示输出日期的月份,%t之后用d表示输出日期的日号              System.out.printf("%1$ty-%1$tm-%1$td; %2$ty-%2$tm-%2$td%n", date, dataL);              // %t之后用Y表示输出日期的年份(4位数的年),              // %t之后用B表示输出日期的月份的完整名, %t之后用b表示输出日期的月份的简称              System.out.printf("%1$tY-%1$tB-%1$td; %2$tY-%2$tb-%2$td%n", date, dataL);                           // 以下是常见的日期组合              // %t之后用D表示以 "%tm/%td/%ty"格式化日期              System.out.printf("%1$tD%n", date);              //%t之后用F表示以"%tY-%tm-%td"格式化日期              System.out.printf("%1$tF%n", date);                           /*** 输出时间类型***/              // 输出时分秒              // %t之后用H表示输出时间的时(24进制),%t之后用I表示输出时间的时(12进制),              // %t之后用M表示输出时间的分,%t之后用S表示输出时间的秒              System.out.printf("%1$tH:%1$tM:%1$tS; %2$tI:%2$tM:%2$tS%n", date, dataL);              // %t之后用L表示输出时间的秒中的毫秒              System.out.printf("%1$tH:%1$tM:%1$tS %1$tL%n", date);              // %t之后p表示输出时间的上午或下午信息              System.out.printf("%1$tH:%1$tM:%1$tS %1$tL %1$tp%n", date);                           // 以下是常见的时间组合              // %t之后用R表示以"%tH:%tM"格式化时间              System.out.printf("%1$tR%n", date);              // %t之后用T表示以"%tH:%tM:%tS"格式化时间              System.out.printf("%1$tT%n", date);              // %t之后用r表示以"%tI:%tM:%tS %Tp"格式化时间              System.out.printf("%1$tr%n", date);                           /*** 输出星期***/              // %t之后用A表示得到星期几的全称              System.out.printf("%1$tF %1$tA%n", date);              // %t之后用a表示得到星期几的简称              System.out.printf("%1$tF %1$ta%n", date);                           // 输出时间日期的完整信息              System.out.printf("%1$tc%n", date);       }}/** *printf方法中,格式为"%s"表示以字符串的形式输出第二个可变长参数的第一个参数值; *格式为"%n"表示换行;格式为"%S"表示将字符串以大写形式输出;在"%s"之间用"n$"表示 *输出可变长参数的第n个参数值.格式为"%b"表示以布尔值的形式输出第二个可变长参数 *的第一个参数值. *//** * 格式为"%d"表示以十进制整数形式输出;"%o"表示以八进制形式输出;"%x"表示以十六进制 * 输出;"%X"表示以十六进制输出,并且将字母(A、B、C、D、E、F)换成大写.格式为"%e"表 * 以科学计数法输出浮点数;格式为"%E"表示以科学计数法输出浮点数,而且将e大写;格式为 * "%f"表示以十进制浮点数输出,在"%f"之间加上".n"表示输出时保留小数点后面n位. *//** * 格式为"%t"表示输出时间日期类型."%t"之后用y表示输出日期的二位数的年份(如99)、用m * 表示输出日期的月份,用d表示输出日期的日号;"%t"之后用Y表示输出日期的四位数的年份 * (如1999)、用B表示输出日期的月份的完整名,用b表示输出日期的月份的简称."%t"之后用D * 表示以"%tm/%td/%ty"的格式输出日期、用F表示以"%tY-%tm-%td"的格式输出日期. *//** * "%t"之后用H表示输出时间的时(24进制),用I表示输出时间的时(12进制),用M表示输出时间 * 分,用S表示输出时间的秒,用L表示输出时间的秒中的毫秒数、用P表示输出时间的是上午还是 * 下午."%t"之后用R表示以"%tH:%tM"的格式输出时间、用T表示以"%tH:%tM:%tS"的格式输出 * 时间、用r表示以"%tI:%tM:%tS %Tp"的格式输出时间. *//** * "%t"之后用A表示输出日期的全称,用a表示输出日期的星期简称. */ 



JDK5.0新特性系列---7.使用ProcessBuilder执行本地命令

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.util.ArrayList;import java.util.Arrays;import java.util.Iterator;import java.util.List;import java.util.Map; /** * 在J2SE5.0之前使用Runtime的exec方法执行本地命令. * 在J2Se5.0之后,可以使用ProcessBuilder执行本地命令 * 它提供的功能更加丰富,能够设置设置工作目录、环境变量等 * 本例PorcessBuilder执行Windows操作系统的"ipconfig/all"命令,获取本机网卡的MAC地址*//**关键技术剖析 * 用本命令名和命令的参数选项构造ProcessBuilder对象,它的start方法执行命令,启动一个进程,返回一个Process对象 * ProcessBuilder的environment方法获得运行进程的环境变量,得到一个Map,可以修改环境变量 * ProcessBuilder的directory方法切换工作目录 * Process的getInputStream方法获得进程的标准输出流,getErrorStream方法获得进程的错误输出流*/public class UsingProcessBuilder {       /**获取Windows系统下的网卡的MAC地址*/       public static List<String> getPhysicalAddress(){              Process p = null;              List<String> address = new ArrayList<String>(); //物理网卡列表              try{                     p = new ProcessBuilder("ipconfig","/all").start(); //执行ipconfig/all命令              }catch(IOException e){                     return address;              }              byte[] b = new byte[1024];              int readbytes = -1;              StringBuffer sb = new StringBuffer();              //读取进程输出值              //在JAVA IO中,输入输出是针对JVM而言,读写是针对外部数据源而言              InputStream in = p.getInputStream();              try{                     while((readbytes = in.read(b)) != -1){                            sb.append(new String(b,0,readbytes));                     }              }catch(IOException e1){              }finally {                     try{                            in.close();                     }catch (IOException e2){                     }              }              //以下是分析输出值,得到物理网卡              String rtValue = sb.toString();              int i = rtValue.indexOf("Physical Address. . . . . . . . . :");              while (i > 0){                     rtValue = rtValue.substring(i + "Physical Address. . . . . . . . . :".length());                     address.add(rtValue.substring(1,18));                     i = rtValue.indexOf("Physical Address. . . . . . . . . :");              }              return address;       }       /**执行自定义的一个命令,该命令放在C:/temp下,并且需要两个环境变量的支持*/       public static boolean executeMyCommand1(){              //创建系统进程创建器              ProcessBuilder pb = new ProcessBuilder("myCommand","myArg1","myArg2");              Map<String, String> env = pb.environment(); //获得进程的环境              //设置和去除环境变量              env.put("VAR1", "myValue");              env.remove("VAR0");              env.put("VAR2", env.get("VAR1") + ";");              //迭代环境变量,获取属性名和属性值              Iterator it=env.keySet().iterator();              String sysatt = null;              while(it.hasNext())              {                     sysatt = (String)it.next();                     System.out.println("System Attribute:"+sysatt+"="+env.get(sysatt));              }              pb.directory(new File("C:/temp"));              try{                     Process p = pb.start(); //得到进程实例                     //等待进程执行完毕                     if(p.waitFor() != 0){                            //如果进程运行结果不为0,表示进程是错误退出的                            //获得进程实例的错误输出                            InputStream error = p.getErrorStream();                            //do something                     }                     InputStream sdin = p.getInputStream(); //获得进程实例的标准输出                     //do something              }catch(IOException e){              }catch(InterruptedException e){              }              return true;       }       public static void executeMyCommand2(){              ProcessBuilder pb = null;              String sysatt = null;              try        {            //创建一个进程示例            pb = new ProcessBuilder("cmd.exe");            //获取系统参数并打印显示            Map<String, String> env = pb.environment();            Iterator it=env.keySet().iterator();            while(it.hasNext())            {                 sysatt = (String)it.next();                System.out.println("System Attribute:"+sysatt+"="+env.get(sysatt));            }            //设置工作目录            pb.directory(new File("d://myDir"));            Process p = pb.start();            //将要执行的Windows命令写入            BufferedWriter bw=new BufferedWriter(newOutputStreamWriter(p.getOutputStream()));            //'/r/n'是必须写入的                 bw.write("test.bat /r/n");            bw.write("ping -t www.yahoo.com.cn /r/n");            //flush()方法是必须调用的            bw.flush();            //将执行结果打印显示            InputStream is = p.getInputStream();            InputStreamReader isr = new InputStreamReader(is, "GBK");            BufferedReader br = new BufferedReader(isr);            String line;            while ((line = br.readLine()) != null)            {                System.out.println(line);            }        }        catch (Exception e)        {            e.printStackTrace();        }       }       public static void main(String[] args){              List<String> address = UsingProcessBuilder.getPhysicalAddress();              for(String add : address){                     System.out.printf("物理网卡地址: %s%n",add);              }              executeMyCommand1();              executeMyCommand2();       }}



JDK5.0新特性系列---8.泛型编程

import java.util.ArrayList;import java.util.Collection;import java.util.List; /** *泛型编程关键掌握两点: *1.在方法参数中使用通配符 *2.在方法的参数类型和返回类型中使用通用类型 *//**关键技术 *1.通配符问号(?)表示任意类型.如"List<?>"表示可以存放任意对象类型的List *2.通配符可以接extends和super,表示有限制的通配符.如"List<? extends Parent>" *  声明的List能且仅能存放Parent及其子类的对象,而"List<? super Child>" *  声明的List仅能存放Child及其父类的对象 *3.通用类型是指不指定参数或者返回值的类型,常用一个大写的字母代表类型, *  它能代表任何类型,需要在方法声明的返回值前用<>声明通用类型.如"public <T> String *  getName(T data)"的方法声明中,String前用<T>表示T是通用类型,它的data参数的类型是T, *  表示能接收任意类型的参数,方法的返回值是String类型 */public class GeneralProgram {       /**使用问号"?*通配符,"?"代表任何类型,所以它的参数可以是任何类型的Collection*/       public static void printCollection(Collection<?> collect){              if(collect == null){                     return;              }              for(Object obj : collect){                     System.out.println(obj + "  ");              }              System.out.println();       }       /**使用有限制的通配符"? extends",可以接受任何Parent及其子类的Collection*/       public static void printNames(Collection<? extends Parent> collect){              if(collect == null){                     return;              }              for(Object obj : collect){                     System.out.println(obj + "  ");              }              System.out.println();       }       /**将一个任意类型的数组添加到列表里*/       public static <T> List<T> arrayToList(T[] datas){              if (datas == null){                     return null;              }              List<T> list_T = new ArrayList<T>();              for(T x : datas){                     list_T.add(x);              }              return list_T;       }       /**在一组parent对象中查找名字为name的Parent对象*/       public static <T extends Parent> T findParent(T[] parents, String name){              if(parents == null){                     return null;              }              T parent = null;              //依次遍历Parent对象数组              for(T x : parents){                     //如果Parent对象的name与参数name匹配,则退出遍历                     if(x.name.equals(name)){                            parent = x;                            break;                     }              }              //返回              return parent;       }       public static void main(String[] args){              /***指定具体的类型***/              //声明一个用于装字符串的列表,该列表只能装字符串的对象              List<String> list_S = new ArrayList<String>();              list_S.add("first");              list_S.add("second");              list_S.add("third");              //不能装整数对象              Integer iObj = 10;              //list_S.add(iObj);//error!!              //从列表中取值时,不用作强制类型转换              String firstS = list_S.get(0);              String thirdS = list_S.get(2);              System.out.println("firstS: " + firstS + "; thirdS: " + thirdS);                           /***泛型和继承***/              //String继承Object              String s = "sss";              Object o = s;              //但List<String>不继承List<Object>              //List<Object> list_O = list_s;//error!!!!!!!!!                           /***通配符***/              //调用具有"?"通配符的方法              List<Integer> list_I = new ArrayList<Integer>();              list_I.add(5555);              list_I.add(6666);              list_I.add(7777);              //该方法可以打印整型列表,也可以打印字符串列表              printCollection(list_I);              printCollection(list_S);                           /***调用具有"?"通配符的方法***/              //只接受父类以及子类类型的列表              List<Parent> list_Parent = new ArrayList<Parent>();              list_Parent.add(new Parent("parentOne"));              list_Parent.add(new Parent("parentTwo"));              list_Parent.add(new Parent("parentThree"));              List<Child> list_Child = new ArrayList<Child>();              list_Child.add(new Child("childOne",20));              list_Child.add(new Child("childTwo",22));              list_Child.add(new Child("childThree",21));              printNames(list_Parent);              printNames(list_Child);              //不能接受其它类型的参数              //printNames(list_S);//error!                           /***泛型方法***/              //arrayToList方法将任意类型的对象数组变成相应的列表              Integer[] iObjs = {55,66,77,88,99};              List<Integer> result_I = arrayToList(iObjs);//转换整型数组              printCollection(result_I);              String[] ss = {"temp","temptemp","hehe","he","hehehe"};              //转换字符串数组              List<String> result_S = arrayToList(ss);              printCollection(result_S);                           //findParent方法在一组Parent对象中根据name查找Parent              Parent[] parents = {new Parent("abc"),new Parent("bcd"),newParent("def")};              Parent parent = findParent(parents, "bcd");              System.out.print("找到的bcd: "+parent);              Child[] children = {new Child("abc",22),new Child("bcd",23),newChild("def",22)};              Child child = findParent(children, "bcd");              System.out.print("找到的bcd: "+child);              //但是不能在字符串数组中进行查找              //String sss = findparent(ss,"temp");//error!       }}class Parent{       public String name;       public Parent(String name){              this.name = name;       }       public String toString(){              return "name = " + this.name;       }}class Child extends Parent{       public int age;       public Child(String name,int age){              super(name);              this.age = age;       }       public String toString(){              return super.toString() + "; age = " + age;       }}



JDK5.0新特性系列---9.注释功能Annotation

import java.lang.annotation.ElementType;import java.lang.annotation.Target;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;/**关键技术 * 1.Java常用的内置注释 *     @Override放在方法的修饰符前,表示该方法覆盖了父类的同名同参数方法,如果该方法没有覆盖父 类的方法而使用了该注释,则编译器会报错 *     @Deprecated放在变量和方法的访问修饰符前,表示该变量或者方法已经不推荐使用,通常是因为它很危险或者存在更好的选择。 * 2.可以自定义注释类型,与enum定义枚举类型一样,使用@interface定义注释类型 * 3. 能在自定义的注释中定义其它类、属性和方法。定义属性时,以属性名为方法名,以属性类型为方法的返回值类型,方法后接default关键字表示属性的默认值。如"String name();"表示该注释类型具有name属性,类型为String;而"int age() default 20;"表示该注释具有age属性,类型为int,默认值为20. * 4. 可以在自定义的注释类型的声明中添加注释,即注释的元注释。Java有2个常用的内置元注释: *    @Target指定Annotation类型可以应用的程序元素,程序元素的类型由java.lang.annotation.ElementType枚举类定义。如ElementType.METHOD表示该注释类型只能用于方法声明中。 *    @Retention和Java编译器处理Annotation类型的方式有关,这些方式由java.lang.annotation.RetentionPolicy枚举值定义。如RetentionPolicy.RUNTIME表示该注释类型 将被编译成class文件 *    @Document指明需要在Javadoc中包含注释(默认是不包含的) */public class AnnotationData {                   @Deprecated private String name;                   public AnnotationData(String name){                                      this.name = name;                   }                                     //方法声明中使用了内置的@Override元数据,表示该方法覆盖了父类的同名同参数方法                   //如果父类不存在该方法,则编译不会通过                   @Override public String toString(){                                      return super.toString() + this.name;                   }                   @Override public int hashCode(){                                      return toString().hashCode();                   }                                     /**方法中使用了内置的@Deprecated元数据,表示该方法已经不被推荐使用了*/                   @Deprecated public String getName(){                                      return name;                   }                   public String getAnnotationDataName(){                                      return this.name;                   }                    //下面定义元数据类型                   //使用@interface声明Annotation类型                   public @interface MyAnnotation{                                      //在元数据中可以定义其它类                                      public enum Severity{                                                         CRITICAL,IMPORTANT,TRIVIAL,DOCUMENT                                      };                                      //定义数据类型不需要定义getter和setter方法                                      //只需要定义一个以成员名称命名的方法,并指定返回类型为需要的数据类型                                      //default关键字为Annotation类型的成员设置默认值                                      Severity severity() default Severity.IMPORTANT;                                      String item();                                      String assignedTo();                                      String dateAssigned();                   }                   //使用自定义的Annotation类型,在使用时,                   //如果Annotation类型在其他的包下,需要与使用类一样,import它                   @MyAnnotation(severity = MyAnnotation.Severity.CRITICAL,                                                           item = "Must finish this method carefully",                                                           assignedTo = "Programmer A",                                                           dateAssigned = "2006/09/10")                   public void doFunction(){                                      //do something                   }                                     //下面再定义一个Annotation类型,使用了元数据的元数据                   //@Retention(RetentionPolicy.RUNNTIME)这个meta-annotation                   //表示了此类型的annotation将编译成class文件,而且还能被虚拟机读取                   //而@Target(ElementType.METHOD)表示此类型的annotation只能用于修饰方法声明                   @Retention(RetentionPolicy.RUNTIME)                   @Target(ElementType.METHOD)                   public @interface MyNewAnnotation{                                                        }}



JDK5.0新特性系列---10.监控与管理虚拟机

import java.lang.management.ClassLoadingMXBean;import java.lang.management.CompilationMXBean;import java.lang.management.GarbageCollectorMXBean;import java.lang.management.ManagementFactory;import java.lang.management.MemoryMXBean;import java.lang.management.OperatingSystemMXBean;import java.lang.management.RuntimeMXBean;import java.lang.management.ThreadMXBean;import java.util.List; /**        本例介绍如何监控和管理Java虚拟机,包括获取Java虚拟机的内存使用情况、线程数、运行时间等。        在J2SE5.0中使用Bean监控和管理Java虚拟机,java.lang.management.ManagementFactory是管理Bean的工厂类,通过它的get系列方法能够获得不同的管理Bean的实例。1. java.lang.management.MemoryMXBean:                                该Bean用于管理Java虚拟机的内存系统。                                                                                                                               一个Java虚拟机具有一个实例。2.java.lang.management.ClassLoadingMXBean:                     该Bean用于管理Java虚拟机的类加载系统。                                                                                                                               一个Java虚拟机具有一个实例。3.java.lang.management.TreadMXBean:                                       该Bean用于管理Java虚拟机的线程系统。                                                                                                                                一个Java虚拟机具有一个实例。4.java.lang.management.RuntimeMXBean:                                 该Bean用于管理Java虚拟机的线程系统。                                                                                                                                一个Java虚拟机具有一个实例。5.java.lang.management.OperatingSystemMXBean:            该Bean用于管理操作系统。                                                                                                                                一个Java虚拟机具有一个实例。6.java.lang.management.CompilationMXBean:                        该Bean用于管理Java虚拟机的编译系统。                                                                                                                                 一个Java虚拟机具有一个实例。7.java.lang.management.GarbageCollectorMXBean:             该Bean用于管理Java虚拟机的垃圾回收系统。                                                                                                                                 一个Java虚拟机具有一个或者多个实例。 */public class JDKMBean {                   public static void printMemoryMXBean(){                                      //获得单一实例                                      MemoryMXBean instance = ManagementFactory.getMemoryMXBean();                                      System.out.printf("%n---%s---%n",instance.getClass().getName());                                      //返回用于对象分配的堆的当前内存使用量                                      System.out.printf("%s: %s%n","HeapMemoryUsage",instance.getHeapMemoryUsage());                                      //返回Java虚拟机使用的非堆内存的当前使用量                                      System.out.printf("%s: %s%n","getNonHeapMemoryUsage",instance.getNonHeapMemoryUsage());                                      instance.gc();                   }                                     public static void printClassLoadingMXBean(){                                      //获得单一实例                                      ClassLoadingMXBean instance = ManagementFactory.getClassLoadingMXBean();                                      System.out.printf("%n---%s---%n",instance.getClass().getName());                                      //返回当前加载到Java虚拟机中的类的数量                                      System.out.printf("%s: %s%n","LoadedClassCount",instance.getLoadedClassCount());                                      //返回自Java虚拟机开始执行到目前已经加载的类的总数                                      System.out.printf("%s: %s%n","TotalLoadedClassCount",instance.getTotalLoadedClassCount());                                      //返回自Java虚拟机开始执行到目前已经卸载的类的总数                                      System.out.printf("%s: %s%n","UnloadedLoadedClassCount",instance.getUnloadedClassCount());                   }                                     public static void printThreadMXBean(){                                      //获得单一实例                                      ThreadMXBean instance = ManagementFactory.getThreadMXBean();                                      System.out.printf("%n---%s---%n",instance.getClass().getName());                                      //返回活动线程的当前数目,包括守护线程和非守护线程                                      System.out.printf("%s: %s%n","ThreadCount",instance.getThreadCount());                                      //返回活动线程ID                                      System.out.printf("%s: %n","Thread IDs");                                      long[] ids = instance.getAllThreadIds();                                      for(long id : ids){                                                         System.out.printf("%s;    ", id);                                      }                                      System.out.println();                                      //返回活动守护线程的当前数目                                      System.out.printf("%s: %s%n","DaemonThreadCount",instance.getDaemonThreadCount());                                      //返回自从java虚拟机启动或峰值重置以来峰值活动线程计数                                      System.out.printf("%s: %s%n","PeakThreadCount",instance.getPeakThreadCount());                                      //返回当前线程的总CPU时间                                      System.out.printf("%s: %s%n","CurrentCpuTime",instance.getCurrentThreadCpuTime());                                      //返回当前线程在用户模式中执行的CPU时间                                      System.out.printf("%s: %s%n","CurrentThreadCpuTime",instance.getCurrentThreadUserTime());                   }                                     public static void printRuntimeMXBean(){                                      //获得单一实例                                      RuntimeMXBean instance = ManagementFactory.getRuntimeMXBean();                                      System.out.printf("%n---%s---%n",instance.getClass().getName());                                      //返回由引导类加载器用于搜索类文件的引导类路径                                      System.out.printf("%s: %s%n","BootClassPath",instance.getBootClassPath());                                      //返回系统类加载器用于搜索类文件的Java类路径                                      System.out.printf("%s: %s%n","ClassPath",instance.getClassPath());                                      //引用传递给Java虚拟机的输入变量,其中不包括传递给main方法的变量                                      System.out.printf("%s: %n","InputArguments");                                      List<String> args = instance.getInputArguments();                                      for(String arg : args){                                                         System.out.printf("%s;  ",arg);                                      }                                      //返回Java库路径                                      System.out.printf("%s: %s%n","LibraryPath",instance.getLibraryPath());                                      //返回正在运行的Java虚拟机实现的管理接口的规范版本                                      System.out.printf("%s: %s%n","ManagementSpecVersion",instance.getManagementSpecVersion());                                      //返回正在运行的Java虚拟机的名称                                      System.out.printf("%s: %s%n","Name",instance.getName());                                                                           //返回Java虚拟机规范名称                                      System.out.printf("%s: %s%n","SpecName",instance.getSpecName());                                      //返回Java虚拟机规范提供商                                      System.out.printf("%s: %s%n","SpecVendor",instance.getSpecVendor());                                      //返回Java虚拟机规范版本                                      System.out.printf("%s: %s%n","SpecVersion",instance.getSpecVersion());                                                                           //返回Java虚拟机实现名称                                      System.out.printf("%s: %s%n","VmName",instance.getVmName());                                      //返回Java虚拟机实现提供商                                      System.out.printf("%s: %s%n","VmVendor",instance.getVmVendor());                                      //返回Java虚拟机实现版本                                      System.out.printf("%s: %s%n","VmVersion",instance.getVmVersion());                                                                           //返回Java虚拟机的启动时间                                      System.out.printf("%s: %s%n","startTime",instance.getStartTime());                                      //返回Java虚拟机的正常运行时间                                      System.out.printf("%s: %s%n","Uptime",instance.getUptime());                   }                                     public static void printOperatingSystemMXBean(){                                      //获得单一实例                                      OperatingSystemMXBean instance = ManagementFactory.getOperatingSystemMXBean();                                      System.out.printf("%n---%s---%n",instance.getClass().getName());                                      //返回操作系统的架构                                      System.out.printf("%s: %s%n","Arch",instance.getArch());                                      //返回Java虚拟机可以使用的处理器数目                                      System.out.printf("%s: %s%n","AvailableProcessors",instance.getAvailableProcessors());                                      //返回操作系统名称                                      System.out.printf("%s: %s%n","Name",instance.getName());                                      //返回操作系统版本                                      System.out.printf("%s: %s%n","Version",instance.getVersion());                   }                                     public static void printCompilationMXBean(){                                      //获得单一实例                                      CompilationMXBean instance = ManagementFactory.getCompilationMXBean();                                      System.out.printf("%n---%s---%n",instance.getClass().getName());                                      //返回即时(JIT)编译器的名称                                      System.out.printf("%s: %s%n","JIT",instance.getName());                                      //返回在编译上花费的累积耗费时间的近似值                                      System.out.printf("%s: %s%n","TotalCompilationTime",instance.getTotalCompilationTime());                   }                                     public static void printGargageCollectorMXBean(){                                      //获得单一实例                                      List<GarbageCollectorMXBean> instances = ManagementFactory.getGarbageCollectorMXBeans();                                      System.out.printf("%n---%s---%n",GarbageCollectorMXBean.class.getName());                                      //遍历每个实例                                      for(GarbageCollectorMXBean instance : instances){                                                         //返回垃圾收集器的名字                                                         System.out.printf("***%s: %s***%n","Name",instance.getName());                                                         //返回已发生的回收的总次数                                                         System.out.printf("%s: %s%n","CollectionCount",instance.getCollectionCount());                                                         //返回近似的累积回收时间                                                         System.out.printf("%s: %s%n","CollectionTime",instance.getCollectionTime());                                      }                   }                                     public static void main(String[] args){                                      JDKMBean.printMemoryMXBean();                                      JDKMBean.printClassLoadingMXBean();                                      JDKMBean.printThreadMXBean();                                      JDKMBean.printRuntimeMXBean();                                      JDKMBean.printOperatingSystemMXBean();                                      JDKMBean.printCompilationMXBean();                                      JDKMBean.printGargageCollectorMXBean();                   }} 



JDK5.0新特性系列---11.1线程 Callable和Future

import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future; /**    从本节开始,主要介绍J2SE5.0与线程相关的新特性,新的线程类主要集中在java.util.concurrent包中,本节实例将介绍如何使用java.util.concurrent.Callable和java.util.concurrent.Future类,用Callable定义一个任务并启动它,然后用它的Future获取输出结果并停止它.关键技术剖析:    关于Callable和Future类的关键技术如下:    1.Callable是类似于Runnable的接口,实现Callable接口的类和实现Runable的类都是可被其他线程执行的任务.    2.Callable和Runnable的区别如下:        1)Callable定义的方法是call,而Runnable定义的方法是run.        2)Callable的call方法可以有返回值,而Runnable的run方法不能有返回值        3)Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常    3.Future表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果.Future的cancel方法取消任务的执行,有一个布尔参数,参数为true表示立即中断任务的执行,参数为false表示允许正在运行的任务运行完成.Future的get方法等待计算完成,获取计算结果. */public class CallableAndFuture {       /**自定义一个任务类,实现Callable接口*/       public static class MyCallableClass implements Callable{              private int flag = 0;              public MyCallableClass(int flag){                     this.flag = flag;              }              public String call() throws Exception{                     if(this.flag == 0){                            return "flag = 0";//如果flag的值为0,则立即返回                     }                     if(this.flag == 1){                            //如果flag的值为1,做一个无限循环                            try{                                   while(true){                                          System.out.println("looping...");                                          Thread.sleep(2000);                                   }                            }catch(InterruptedException e){                                   System.out.println("Interrupted");                            }                            return "false";                     }else{                            throw new Exception("Bad flag value!");//flag不为1或0,则抛出异常                     }              }       }       public static void main(String... args){              //定义3个Callable类型的任务              MyCallableClass task1 = new MyCallableClass(0);              MyCallableClass task2 = new MyCallableClass(1);              MyCallableClass task3 = new MyCallableClass(2);                           //创建一个执行任务的服务              ExecutorService es = Executors.newFixedThreadPool(3);              try{                     //提交并执行任务,任务启动时返回了一个Future对象                     //如果想得到任务执行的结果或者是异常可对这个Future对象进行操作                     Future future1 = es.submit(task1);                     //获得第一个任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行                     System.out.println("task1: " + future1.get());                                         Future future2 = es.submit(task2);                     //等待5秒后,再停止第二个任务,因为第二个任务进行的是无限循环                     Thread.sleep(5000);                     System.out.println("task2 cancel: " + future2.cancel(true));                                         //获取第三个任务的输出,因为执行第三个任务会引起异常                     //所以下面的语句将引起异常的输出                     Future future3 = es.submit(task3);                     System.out.println("task3: " + future3.get());              }catch(Exception e){                     System.out.println(e.toString());              }              es.shutdown();//立即停止任务执行服务       }}



JDK5.0新特性系列---11.2线程 任务执行架构

import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit; /**    在J2SE之前启动一个任务是通过调用Thread类的start方法来实现的,任务的提交和执行是同时进行的,如果想对任务的执行进行调度,或是控制同时执行的线程数量就需要额外的编写代码来完成.    J2SE5.0提供了一个新的任务执行架构,可以轻松地高度和控制任务的执行,并且可以建立一个线程池来执行任务.    实例介绍如何使用新的任务执行架构,运行Runnable和Callable任务,包括定时执行任务,按规律执行任务和停止任务.关键技术剖析:    使用新的任务执行框架的关键技术如下:    1.Executor服务对象是用来执行Runnable任务的,常用的方法如下:      execute方法用于执行Runnable类型的任务.    2.ExecutorService服务对象能执行和终止Callable任务,它继承了Executor,所以也能执行Runnable任务.常用的方法如下      a) submit方法用来提交Callable或Runnable任务,并返回代表此任务的Future对象.      b) invokeAll方法批处理任务集合,并返回一个代表这些任务的Future对象集合      c) shutdown方法在完成自己已提交的任务后关闭服务,不再接受新任务.      d) shutdownNow方法停止所有正在执行的任务并关闭服务.      e) isTerminated测试是否所有任务都执行完毕了      g) isShutdown测试是否该ExecutorService已被关闭    3.ScheduledExecutorService服务对象继承ExecutorService,提供了按时间安排执行任务的功能.常用的方法如下:      a)schedule(task,initDelay)方法安排所提交的Callable或Runnable任务在initDelay指定的时间后执行.      b)scheduleAtFixedRate方法安排所提交的Runnable任务按指定的间隔重复执行.      c)scheduleWithFixedDelay方法安排所提交的Runnable任务在每次执行完后,等待delay所指定的时间后重复执行.    4.Executors类用来创建各种服务对象,常用的方法如下:      a)callable(Runnable task)方法将Runnable的任务转化成Callable的任务.      b)newSingleThreadExecutor方法产生一个ExecutorService对象,这个对象带有一个线程池,线程池的大小会根据需要调整,线程执行完任务后返回线程池,供执行下一次任务使用.      c)newCachedThreadPool方法会产生一个ExecutorService对象,这个对象带有一个线程池,线程池的大小会根据需要调整,线程执行完任务后返回线程池,供执行下一次任务使用.      d)newFixedThreadPool(int poolSize)方法产生一个ExecutorService对象,这个对象带有一个大小为poolSize的线程池,若任务数量大于poolSize,任务会被放在一个队列里顺序执行.      e)newSingleThreadScheduledExecutor方法产生一个ScheduledExecutorService对象,这个对象的线程池大小为1,若任务多于一个,任务将按先后顺序执行.      f)newScheduledThreadPool(int poolSize)方法产生一个ScheduledExecutorService对象,这个对象的线程池大小为poolSize,若任务数量大于poolSize,任务会在一个队列里等待执行.*/public class ExecuteArch {       /**该线程输出一行字符串*/       public static class MyThread implements Runnable{              public void run(){                     System.out.println("Task repeating. " + System.currentTimeMillis());                     try{                            Thread.sleep(1000);                     }catch(InterruptedException e){                            System.out.println("Task interrupted. " + System.currentTimeMillis());                     }              }       }       /**该Callable结束另一个任务*/       public static class MyCallable implements Callable{              private Future future;              public MyCallable(Future future){                     this.future = future;              }              public String call(){                     System.out.println("To cancell Task..." + System.currentTimeMillis());                     this.future.cancel(true);                     return "Task cancelled!";              }       }             public static void main(String... args)throwsInterruptedException,ExecutionException{              //产生一个ExcutorService对象,这个对象带有一个线程池,线程池的大小会根据需要调整              //线程执行完任务后返回线程池,供执行下一次任务使用              ExecutorService cachedService = Executors.newCachedThreadPool();              Future myThreadFuture = cachedService.submit(new MyThread());              Future myCallableFuture = cachedService.submit(newMyCallable(myThreadFuture));              System.out.println(myCallableFuture.get());              System.out.println("--------------------");                           //将Runnable任务转换成 Callable任务              Callable myThreadCallable = Executors.callable(new MyThread());              Future myThreadCallableFuture = cachedService.submit(myThreadCallable);              //对于Runnable任务,转换成Callable任务后,也没有返回值              System.out.println(myThreadCallableFuture.get());              cachedService.shutdownNow();              System.out.println("--------------------");                           //产生一个ExecutorService对象,这个对象带有一个大小为poolSize的线程池              //若任务大于poolSize,任务会被放在一个queue里顺序执行              ExecutorService fixedService = Executors.newFixedThreadPool(2);              fixedService.submit(new MyThread());              fixedService.submit(new MyThread());              //由于线程池大小为2,所以后面的任务必须等待前面的任务执行完毕后才能被执行              myThreadFuture = fixedService.submit(new MyThread());              myThreadFuture = fixedService.submit(new MyCallable(myThreadFuture));              System.out.println(myCallableFuture.get());              fixedService.shutdown();              System.out.println("--------------------");                           //产生一个ScheduleExecutorService对象,这个对象的线程池大小为poolSize              //若任务数量大于poolSize,任务会在一个queue里等待执行              ScheduledExecutorService fixedScheduledService = Executors.newScheduledThreadPool(2);              MyThread task1 = new MyThread();              //使用任务执行服务立即执行任务1,而且此后每隔2秒执行一次任务1              myThreadFuture = fixedScheduledService.scheduleAtFixedRate(task1, 0, 2, TimeUnit.SECONDS);              MyCallable task2 = new MyCallable(myThreadFuture);              //使用任务执行服务等待5秒后执行任务2,执行它后将任务1关闭.              myCallableFuture = fixedScheduledService.schedule(task2,5,TimeUnit.SECONDS);              System.out.println(myCallableFuture.get());              fixedScheduledService.shutdownNow();                   }}



JDK5.0新特性系列---11.3线程 锁Lock

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantLock;import java.util.concurrent.locks.ReentrantReadWriteLock;  /**    在多线程编程里,一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性,在进行事务性操作时需要将共享资源锁定,这样可以保证只有一个线程能对资源进行操作,从而保证了数据的完整性.在J2SE5.0以前锁定的功能是由synchronized关键字来实现的.本节实例介绍如何使用J2SE 5.0中的新特性实现锁定,包括一般的锁、读写锁等.关键技术剖析:    在J2SE5.0中的锁是由java.util.concurrent.locks.lock实现的,使用它的关键技术点如下:    1.ReentrantLock类实现了Lock接口,通过它可以完全取代synchronized关键字.    2.ReentrantLock的lock方法取得锁,如果该锁定没有被其他线程占据,则获取该锁定并返回,将保持计数器置为1;如果当前线程已经占据锁,则立即返回,将保持计数器加1;如果锁定被其他线程占据,则当前线程进入睡眠状态,等待其他线程释放锁,此时保持计数器置为1.    3.ReentrantLock的unlock方法释放锁,如果当前线程是锁的占有者,则将保持计数器减1,如果保持计数器等于0,则释放锁.如果当前线程不是锁的占有者,则抛出异常.    4.ReadWriteLock是一个继承Lock的接口,定义了读写锁.它的一个实现类是ReentrantReadWriteLock    5.ReentrantReadWriteLock的writeLock方法获得用于写入操作的锁定,当获得写入锁时,其他线程想进行读写操作都必须等待.    6.ReentrantReadWriteLock的readLock方法获得用于读操作的锁定,当获得读取锁时,其他读的线程可以继续获得读取锁,但是不能获得写入锁.   */public class Lockers {       /**测试Lock的使用.在方法中使用Lock,可以避免使用synchronized关键字*/       public static class LockTest{              Lock lock = new ReentrantLock();//锁              double value = 0d; //值              int addtimes = 0;              /**               * 增加value的值,该方法的操作分为2岁,而且相互依赖,必须实现在一个事务中               * 所以该方法必须同步,以前的做法是在方法声明中使用synchronized关键字               */              public void addValue(double v){                     lock.lock();//锁住锁                     System.out.println("LockTest to addValue: " + v + " " + System.currentTimeMillis());                     try {                            Thread.sleep(1000);                     }catch(InterruptedException e){                     }                     this.value += v;                     this.addtimes++;                     lock.unlock();              }              public double getValue(){                     return this.value;              }       }       public static void testLockTest() throws Exception{              final LockTest lockTest = new LockTest();              //新建任务1,调用lockTest的addValue方法              Runnable task1 = new Runnable(){                     public void run(){                            lockTest.addValue(55.55);                     }              };              //新建任务2,调用lockTest的getValue方法               Runnable task2 = new Runnable(){                      public void run(){                             System.out.println("value: " + lockTest.getValue());                      }               };               //新建任务执行服务               ExecutorService cachedService = Executors.newCachedThreadPool();               Future future = null;               //同时执行任务1三次,由于 addValue方法使用了锁机制,所以,实质上会顺序执行               for(int i=0;i<3;i++){                      future = cachedService.submit(task1);               }               future.get();//等待最后一个任务1被执行完               future = cachedService.submit(task2);//再执行任务2,输出结果               future.get();//等待任务2执行完后,关闭任务执行服务               cachedService.shutdownNow();       }       /**        * ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock        * 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock        * 而且写的Lock被锁定后,任何线程都不能得到Lock.ReadWriteLock提供的方法有:        * readLock():返回一个读的Lock        * writeLock():返回一个写的lock,此lock是排它的        * ReadWriteLockTest很适合处理类似文件的读写操作        * 读的时候可以同时读,但是不能写,写的时候既不能同时写,也不能读        */       public static class ReadWriteLockTest{              ReadWriteLock lock = new ReentrantReadWriteLock();//锁              double value = 0d; //值              int addtimes = 0;              /**增加value的值,不允许多个线程同时进入该方法*/              public void addValue(double v){                     //得到writeLock并锁定                     Lock writeLock = lock.writeLock();                     writeLock.lock();                     System.out.println("ReadWriteLockTest to addValue: " + v + " " + System.currentTimeMillis());                     try{                            Thread.sleep(1000);                     }catch(InterruptedException e){                                             }                     try{                            //做写的工作                            this.value += v;                            this.addtimes++;                     }finally{                            writeLock.unlock();                     }              }              /**               *获得信息.当有线程在调用addValue方法时,getInfo得到的信息可能是不正确的.               *所以,也必须保证该方法在被调用时,没有方法在调用addValue方法.               */              public String getInfo(){                     //得到 readLock并锁定                     Lock readLock = lock.readLock();                     readLock.lock();                     System.out.println("ReadWriteLockTest to getInfo "+System.currentTimeMillis());                     try{                            Thread.sleep(1000);                     }catch(InterruptedException e){                     }                     try{                            return this.value + " : " + this.addtimes;//做读的工作                     }finally{                            readLock.unlock();//释放readLock                     }              }       }       public static void testReadWriteLockTest() throws Exception{              final ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();              //新建任务1,调用lockTest的addValue方法              Runnable task_1 = new Runnable(){                     public void run(){                            readWriteLockTest.addValue(55.55);                     }              };              //新建任务2,调用lockTest的getValue方法              Runnable task_2 = new Runnable(){                     public void run(){                            System.out.println("info " + readWriteLockTest.getInfo());                     }              };              //新建任务任务执行服务              ExecutorService cachedService_1 = Executors.newCachedThreadPool();              Future future_1 = null;              //同时执行5个任务,其中前2个任务是任务1,后两个任务是任务2              for(int i=0;i<2;i++){                     future_1 = cachedService_1.submit(task_1);              }              for(int i=0;i<2;i++){                     future_1 = cachedService_1.submit(task_2);              }              //最后一个任务是任务1              future_1 = cachedService_1.submit(task_1);              //这5个任务的执行顺序应该是              //第一个任务1先执行,第二个任务1再执行;这是因为不能同时写,所以必须等              //然后两个任务2同时执行;这是因为在写的时候,就不能读,所以都等待写结束              //又同时可以同时读,所以它们同时执行              //最后一个任务1再执行.这是因为在读的时候,也不能写,所以必须等待读结束后,              //才能写.等待最后一个任务2被执行完              future_1.get();              cachedService_1.shutdownNow();       }       public static void main(String... args)throws Exception{              Lockers.testLockTest();              System.out.println("--------------------------");              Lockers.testReadWriteLockTest();       }}/** * ReentrantReadWriteLock  获取顺序如下: * This class does not impose a reader or writer preference ordering for lock access. * However, it does support an optional fairness policy. * When constructed as fair, threads contend for entry using an approximatelyarrival-order policy. * When the write lock is released either the longest-waiting single writer will beassigned the write lock, or if there is a reader waiting longer than any writer, theset of readers will be assigned the read lock. * When constructed as non-fair, the order of entry to the lock need not be in arrivalorder. * In either case, if readers are active and a writer enters the lock then nosubsequent readers will be granted the read lock until after that writer has acquiredand released the write lock.*/



JDK5.0新特性系列---11.4线程 Condition 

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock; /** *有时候线程取得lock后需要在一定条件下才能做某些工作,比如经典的Producer和Consumer问题 *在Java 5.0以前,这种功能是由Object类的wait(),notify()和notifyAll()等方法实现的 *在5.0里面,这些功能集中到了Condition这个接口实现 *//** * 使用Condition的关键技术点如下: * 1.通过Lock的newCondition方法创建Condition的对象 * 2.Condition的await方法使当前线程进入等待状态,并且释放它占据的Lock,直到有其他的线程唤醒当前线程时,重新占有Lock. * 3.Condition的signal方法唤醒其他正在等待该Condition的线程. */public class ConditionTest {    /**     * 篮子程序,这里为了简化问题,篮子中最多只能有一个苹果     * Consumer必须在篮子里有苹果的时候才能吃苹果,否则它必须暂时放弃对篮子的锁定     * 等到Producer往篮子里放了苹果后再去拿来吃。     * 否则它也需要暂时解锁等Comsumer把苹果吃了才能往篮子里放苹果。     */    public static class Basket{        //锁        Lock lock = new ReentrantLock();        //根据锁产生Condition对象        Condition produced = lock.newCondition();        Condition consumed  = lock.newCondition();        //篮子里的苹果数,最多为1        int num = 0;        //生产苹果,往篮子里放        public void produce() throws InterruptedException{            //获得锁            lock.lock();            System.out.println("Producer get a lock...");                      try{                //判断是否满足生产条件                while(num == 1){                    //如果有苹果,则不生产,放弃锁,进入睡眠                    //等待消费者消费                    System.out.println("Producer sleep...");                    consumed.await();                    System.out.println("Producer awaked...");                }                //生产苹果                Thread.sleep(500);                System.out.println("Producer produced an Apple.");                num = 1;                //通知等待produced Condition的线程                produced.signal();            }finally{                lock.unlock();            }        }        //消费苹果,从篮子里取        public void consume() throws InterruptedException{            //获得锁            lock.lock();            System.out.println("Consumer get a lock...");            try{                //判断是否满足消费条件                while(num == 0){                    //如果没有苹果,无法消费,则放弃锁,进入睡眠                    //等待生产者生产苹果                    System.out.println("Consumer sleep...");                    produced.await();                    System.out.println("Consumer awaked...");                }                //吃苹果                Thread.sleep(500);                System.out.println("Consumer consumed an Apple.");                num = 0;                //发信号唤醒某个等待consumed Condition的线程                            consumed.signal();            } finally {                lock.unlock();            }        }    }    //测试Basket程序    public static void testBasket() throws Exception{        final Basket basket = new Basket();        //定义一个producer        Runnable producer  = new Runnable(){            public void run() {                try{                    basket.produce();                }catch(InterruptedException ex){                    ex.printStackTrace();                }            }                   };        //定义一个consumer        Runnable consumer = new Runnable(){            public void run(){                try{                    basket.consume();                }catch(InterruptedException ex){                    ex.printStackTrace();                }            }        };        //各生产3个consumer和producer        ExecutorService service = Executors.newCachedThreadPool();        for(int i = 0; i <3; i++){            service.submit(producer);        }        for(int i = 0;i<3;i++){            service.submit(consumer);        }        service.shutdown();    }    public static void main(String... args)throws Exception{        ConditionTest.testBasket();    }}



JDK5.0新特性系列---11.5.1线程 同步装置之Semaphore

import java.util.ArrayList;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock; /** *Java 5.0里新增加了4个协调线程间进程的同步装置,它们分别是:Semaphore,CountDownLatch,CyclicBarrier和Exchanger *Semaphore可以控制运行线程的个数 *Semaphore是一个用来管理资源池的工具,可以看成是个通行证,线程要想从资源池拿到资源必须先拿到通行证,如果线程暂时拿不到通告证,线程就会被阻断,进入等待状态. *//** *使用Semaphore的关键技术点如下: *1.在构造Semaphore对象时,必须提供通行证的数目,如"newSemaphore(3)"将创建一个具有3个通行证的Semaphore对象,一旦该对象被创建,其通行证数量是不能改变的. *2.Semaphore的acquire方法取得一个通行证,如果通行证已经发完了,当前线程将进入等待状态,直到有其他线程释放了通行证. *3.Semaphore的release方法释放了资源池. */public class SemaphoreTest {       /**        * 模拟资源池的类        * 只为池发放2个通行证,即同时只允许2个线程获得池中的资源        */       public static class Pool{              ArrayList<String> pool = null;  //保存资源池中的资源              Semaphore pass = null; //通行证              Lock lock = new ReentrantLock();              public Pool(int size){                     //初始化资源池                     pool = new ArrayList<String>();                     for(int i = 0; i < size; i++){                            pool.add("Resource " + i);                     }                     //发送2个通行证                     pass = new Semaphore(2);              }              public String get()throws InterruptedException{                     //获取通行证,只有得到通行证后才能得到资源                     System.out.println("Try to get a pass...");                     pass.acquire();                     System.out.println("Got a pass");                     return getResource();              }              private String getResource(){                     lock.lock();                     String result = pool.remove(0);                     System.out.println("资源 " + result + "被取走");                     lock.unlock();                     return result;              }              public void put(String resource){                     //归还通行证,并那还资源                     System.out.println("Released a pass");                     pass.release();                     releaseResource(resource);              }              private void releaseResource(String resource){                     lock.lock();                     System.out.println("资源 " + resource + " 被归还");                     pool.add(resource);                     lock.unlock();              }       }       public static void testPool(){              //准备10个资源的资源池              final Pool aPool = new Pool(10);              Runnable worker = new Runnable(){                     @Override                     public void run() {                            String resource = null;                            try{                                   resource = aPool.get();//取得resource                                   //用resource做工作                                   System.out.println("I finished on " + resource);                                   Thread.sleep(500);                                   System.out.println("I finished on " + resource);                            }catch(InterruptedException ex){                            }                            aPool.put(resource);                     }                                        };              //启动5个任务              ExecutorService service = Executors.newCachedThreadPool();              for(int i = 0; i<5; i++){                     service.submit(worker);              }              service.shutdown();       }       public static void main(String... args){              SemaphoreTest.testPool();       }}



JDK5.0新特性系列---11.5.2线程 同步装置之CountDownLatch

import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * CountDownLatch维护一个计数器,等待这个CountDownLatch的线程必须等到计数器为0时才可以继续. * 以下实例模拟服务器的启动,假设启动一个服务器需要初始化3个组件,当3个组件初始化完毕后,服务器才算成功启动. *//** * 使用CountDownLatch的关键技术点如下: * 1.构造CountDownLatch对象时,需要指定计数器的初始值,该值必须大于等于0,一旦对象被创建,其初始值将不能被改变. * 2.CountDownLatch的await方法使当前线程进入等待状态,直到计数器为0 * 3.CountDownLatch的 和countDown方法使计数器减1. */public class CountDownLatchTest {  /** 初始化组件的线程 */  public static class ComponentThread implements Runnable {    CountDownLatch latch; //计数器    int ID; //组件ID    //构造方法    public ComponentThread(CountDownLatch latch, int ID) {      this.latch = latch;      this.ID = ID;    }    public void run() {      //初始化组件      System.out.println("Initializing component " + ID);      try {        Thread.sleep(500 * ID);      }      catch (InterruptedException e) {}      System.out.println("Component " + ID + " initialized!");      latch.countDown(); //将计数器减1    }  }  /** 启动服务器 */  public static void startServer() throws Exception {    System.out.println("Server is starting.");    //初始化一个初始值为3的CountDownLatch    CountDownLatch latch = new CountDownLatch(3);    //启动3个线程分别去3个组件    ExecutorService service = Executors.newCachedThreadPool();    service.submit(new ComponentThread(latch, 1));    service.submit(new ComponentThread(latch, 2));    service.submit(new ComponentThread(latch, 3));    service.shutdown();    latch.await();//等待3个组件的初始化工作都完成    System.out.println("Server is up!");//当所需的三个组件都完成时,Server就可以继续了  }  public static void main(String... args) throws Exception {    CountDownLatchTest.startServer();  }}



JDK5.0新特性系列---11.5.3线程 同步装置之CyclicBarrier 

import java.util.Random;import java.util.concurrent.CyclicBarrier; /** * CyclicBarrier维持一个计数器,与CountDownLatch不同的是,等待这个CyclicBarrier的线程必须等到计数器的某个值时,才可以继续. * CyclicBarrier就像它名字的意思一样,可看成是个障碍,所有的线程必须到齐后才能一起通过这个障碍. *//** * 本实例实现一个数组相邻元素的加法,一个线程给数组的第一个元素赋值,然后等待其它线程给数组第二个元素赋值,然后将第一个元素和第二个元素相加. *//** * CyclicBarrier的关键技术点如下: * 1.构造CyclicBarrier对象时,需要指定计数器的目标值,计数器的初始值为0. * 还可以在构造方法中带一个 Runnable参数,表示当计数器到达目标值是,在等待CyclicBarrier的线程被唤醒之前,指定该Runnable任务. * 2.CyclicBarrier的await方法使当前线程进入等待状态,同时将计数器值加1,当计数器到达目标值时,当前线程被唤醒. */public class CyclicBarrierTest {       public static class ComponentThread implements Runnable{              CyclicBarrier barrier;//计数器              int ID;//组件              int[] array; //数据数组              public ComponentThread(CyclicBarrier barrier,int[] array,int ID){                     this.barrier = barrier;                     this.ID = ID;                     this.array = array;              }              public void run(){                     try{                            //Random的nextInt(int n)方法返回一个[0,n)范围内的随机数                            array[ID] = new Random().nextInt(100);                            System.out.println("Componet " + ID + " sleep...");                            barrier.await();                            System.out.println("Componet " + ID + " awaked...");                            //计算数据数组中的当前值和后续值                            int result = array[ID] + array[ID + 1];                            System.out.println("Component " + ID + " result: " + result);                     }catch(Exception ex){                     }              }       }       /**测试CyclicBarrier的用法*/       public static void testCyclicBarrier(){              final int[] array = new int[3];              CyclicBarrier barrier = new CyclicBarrier(2,new Runnable(){                     public void run(){                            System.out.println("testCyclicBarrier run...");                            array[2] = array[0] + array[1];                     }              });              //启动线程              new Thread(new ComponentThread(barrier,array,0)).start();              new Thread(new ComponentThread(barrier,array,1)).start();       }       public static void main(String... args){              CyclicBarrierTest.testCyclicBarrier();       }}



JDK5.0新特性系列---11.5.4线程 同步装置之Exchanger

/** * Exchanger让两个线程互换信息 * 实例模拟服务生和顾客,服务生往空杯子中倒水,顾客从装满水的杯子中喝水,然后互换杯子,服务生接着倒水,顾客接着喝水. *//** * 使用Exchanger的关键技术点如下: * 1.初始化Exchanger对象时,可以通过泛型指定杯子能交换的信息类型.如"new Exchanger<String>;"表示只能交换String类型的信息 * 2.Exchanger的exchange方法表示当前线程准备交换信息,等待其他线程与它交换信息.当有其他线程调用该Exchanger对象的exchange方法时,立即交换信息 */public class ExchangerTest {       //描述一个装水的杯子       public static class Cup{              private boolean full = false; //标识杯子是否有水              public Cup(boolean full){                     this.full = full;              }              //添水,假设需要5s              public void addWater(){                     if(!this.full){                            try{                                   Thread.sleep(5000);                            }catch(InterruptedException e){                            }                            this.full = true;                     }              }              //喝水,假设需要10s              public void drinkWater(){                     if(this.full){                            try{                                   Thread.sleep(10000);                            }catch(InterruptedException e){                                                              }                            this.full = false;                     }              }       }       public static void testExchanger(){              //初始化一个Exchanger,并规定可交换的信息类型是杯子              final Exchanger<Cup> exchanger = new Exchanger<Cup>();              //初始化一个空的杯子和装满水的杯子              final Cup initialEmptyCup = new Cup(false);              final Cup initialFullCup = new Cup(true);                           //服务生线程              class Waiter implements Runnable{                     public void run(){                            Cup currentCup = initialEmptyCup;                            try{                                   int i = 0;                                   while(i < 2){                                          System.out.println("服务生开始往杯子里倒水: " + System.currentTimeMillis());                                          //往空的杯子里倒水                                          currentCup.addWater();                                          System.out.println("服务生添水完毕: " + System.currentTimeMillis());                                          //杯子满后和顾客的空杯子交换                                          System.out.println("服务生等待与顾客交换杯子: " + System.currentTimeMillis());                                          currentCup = exchanger.exchange(currentCup);                                          System.out.println("服务生与顾客交换杯子完毕: " + System.currentTimeMillis());                                          i++;                                   }                            }catch(InterruptedException ex){                            }                     }              }              //顾客线程              class Customer implements Runnable{                     public void run(){                            Cup currentCup  = initialFullCup;                            try{                                   int i = 0;                                   while(i < 2){                                          System.out.println("顾客开始喝水: " + System.currentTimeMillis());                                          //把杯子里的水喝掉                                          currentCup.drinkWater();                                          System.out.println("顾客喝水完毕: " + System.currentTimeMillis());                                          //将空杯子和服务生的满杯子交换                                          System.out.println("顾客等待与服务生交换杯子: " + System.currentTimeMillis());                                          exchanger.exchange(currentCup);                                          System.out.println("顾客与服务生交换杯子完毕: " + System.currentTimeMillis());                                          i++;                                   }                            }catch(InterruptedException ex){                            }                     }              }              new Thread(new Waiter()).start();              new Thread(new Customer()).start();       }       public static void main(String... args){              ExchangerTest.testExchanger();       }}/**Waiter是模拟服务生的线程,首先往空杯子中添水,然后调用Exchanger的exchange方法,等待和别人交换杯子.Customer是模拟了顾客的线程,首先把装满水的杯子喝光,然后调用Exchange的exchange方法,等待和别人交换杯子.当服务生和顾客都准备交换杯子时,由Exchanger将服务生手中装满水的杯子和顾客手中的空杯子交换.服务生可以继续倒水,而顾客可以继续喝水.*/



JDK5.0新特性系列---11.6线程 BlockingQueue

importjava.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; /**    本例介绍一个特殊的队列:BlockingQueue,如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒.同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有空间才会被唤醒继续操作.    本例再次实现11.4线程----条件Condition中介绍的篮子程序,不过这个篮子中最多能放的苹果数不是1,可以随意指定.当篮子满时,生产者进入等待状态,当篮子空时,消费者等待. *//**    使用BlockingQueue的关键技术点如下:    1.BlockingQueue定义的常用方法如下:        1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则招聘异常        2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.        3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.        4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null        5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止    2.BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类        1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.        2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的        3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.        4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.    3.LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue.          */public class BlockingQueueTest {       /**定义装苹果的篮子*/       public static class Basket{              //篮子,能够容纳3个苹果              BlockingQueue<String> basket = new ArrayBlockingQueue<String>(3);              //生产苹果,放入篮子              public void produce() throws InterruptedException{                     //put方法放入一个苹果,若basket满了,等到basket有位置                     basket.put("An apple");              }              //消费苹果,从篮子中取走              public String consume() throws InterruptedException{                     //take方法取出一个苹果,若basket为空,等到basket有苹果为止                     return basket.take();              }       }       //测试方法       public static void testBasket(){              final Basket basket = new Basket();//建立一个装苹果的篮子              //定义苹果生产者              class Producer implements Runnable{                     public void run(){                            try{                                   while(true){                                          //生产苹果                                          System.out.println("生产者准备生产苹果: " + System.currentTimeMillis());                                          basket.produce();                                          System.out.println("生产者生产苹果完毕: " + System.currentTimeMillis());                                          //休眠300ms                                          Thread.sleep(300);                                   }                            }catch(InterruptedException ex){                            }                     }              }              //定义苹果消费者              class Consumer implements Runnable{                     public void run(){                            try{                                   while(true){                                          //消费苹果                                          System.out.println("消费者准备消费苹果: " + System.currentTimeMillis());                                          basket.consume();                                          System.out.println("消费者消费苹果完毕: " + System.currentTimeMillis());                                          //休眠1000ms                                          Thread.sleep(1000);                                   }                            }catch(InterruptedException ex){                            }                     }              }              ExecutorService service = Executors.newCachedThreadPool();              Producer producer = new Producer();              Consumer consumer = new Consumer();              service.submit(producer);              service.submit(consumer);              //程序运行5s后,所有任务停止              try{                     Thread.sleep(5000);              }catch(InterruptedException ex){              }              service.shutdownNow();       }       public static void main(String[] args){              BlockingQueueTest.testBasket();       }} 


0 0
原创粉丝点击