java基础(三)

xiaoxiao2021-02-28  12

                                                                             JAVAse基础(三)

1. 可变字符串,包装类,日期

1.  可变字符串

StringBuffer概述-----字符串缓冲区(StringBffer是线程安全的可变字符串)

面试题:String和StringBuffer的区别-----String一单被创建后,值不能被改变,如果参与了操作,引用发生了变化,不是在原有的的字符串上操作,而是产生了一个新的字符串,StringBuffer是线程安全可变字符串,但是效率稍低

StringBuffer的用法:

可以用append的方法追加字符串,也可以追加一个对象

可变字符串的修改---插入

Insert的方法可以根据索引进行插入字符串,也可以插入所有的数据类型,在指定的索引位置插入字符串,不能超出原本的字符串长度

StringBuffer可以替换,也可以反转

2. 随机数Random

可以用数学函数Math.Random来生成随机数,也可以直接用Random来生成,种子的随机数只会生成一次 例如:Random r=newRandom(里面是数字,称为种子)

3. System类

System.currentTimeMillis();----获取当前时间的毫秒数

System.Eixt----退出当前jvm执行的程序

System.gc------调用垃圾回收器

4. 包装类

把基本数据类型转换成类,我们使用基本数据类型做进制很麻烦,对于临街值也不好判断,我们的包装类提供了很多的方法供我们使用,这样会方便很多

基本数据类型  byte   short     int           long        float      double    char               boolean

包装类  byte    short    integer     long       flost      double   character        Boolean

Intrger类在对象中包含了一个基本类型int的值

例如   Byte by=new Byte(“哈”)                          integer   in = new integer(12);

5. 自动装箱和拆箱和包装类默认值

基本数据类型------------------------------à包装类(jdk1.5特性,自动完成)

通过包装类可以把一个整数类型给一个integer包装类,也可以把包装类的值给一个相同的数据类型

Int和integer区别

Int是数据类型,integer是包装类,包装类中提供了很多对整数操作的方法,他们之间可以自动装箱和拆箱,int默认值是0;integer默认值是null

对象在使用前要判断是否为空在使用

6. 日期类Date

   getTime-----返回字1970年到现在的毫秒数

日历类Calendar-----是一个抽象类,他的子类有GregorianCalendar

Calendar gc = Calendar.getInstance();

    intyear=gc.get(Calendar.YEAR);

    intmonth=gc.get(Calendar.MONTH);

    System.out.println(year+""+month+"");

7. 集合体系

1.Arraylist集合

数组和集合的区别

数组:长度固定,可以存储数据类型,也可以存储对象

集合:长度可变,只能存储对象类型,(由于有包装类的存在,集合中可以存储任意类型)

什么是集合

集合也叫容器用于存储对象

集合的体系

Arraylist元素可以重复,因为索引不同,也可以添加null元素

Collection coll = new ArrayList();

Collection----listset集合的超级接口

 

集合的添加

add和addall    

接口不能继承类,接口只能继承接口

集合不限制长度

Collection的常用方法------集合中可以存储集合

Clear()方法是清空集合

Remove()方法指定删除集合中的值

Remove()方法是指在集合中删除另一个集合

ContainsAll()方法是指在集合中是否包含某个集合的内容

isEmpty()方式判断集合是否为空

集合转换成数组   Object [ ] obj=xxx.toArray();

迭代器(Iterator)----集合的遍历

       在开始的时间迭代器会指在一个集合的一个空位置,用while循环 while(iter .hasNext())

       iterator iter=xxx. iterator();-----创建迭代器

       iter .hasNext()方法是判断集合有没有下一个值

       迭代器只能用一次,用完之后要在用的话还要在创建一个迭代器

     List的实现类

       Arraylist---Arraylist中的元素和可以重复,是有序的集合,长度不固定,不是线程安全的,效率高

       Vector-------他是线程安全的

       LinkedList-----list接口的链接列表实现,他不是线程安全的

栈---后进先出

队列---先进先出

考虑安全---牺牲性能

集合中泛型的使用

集合中可以存储任何的数据类型,实际情况下都是存储一种数据类型,我们可以通过泛型来指定这种数据类型

可以有继承关系的父子类添加到集合里面,例如把子类集合的元素可以加到父类里面

迭代器有Iteratorlist Iterator

自定义泛型

        在类名的后面加泛型标记

        泛型类

publicclass FanXinZDY<T> {

 

 

  private T[] arr;

 

  public T[] getArr() {

     returnarr;

  }

 

  publicvoid setArr(T[] arr) {

     this.arr = arr;

  }

  public T getByIndex(int index){

     returnarr[index];

  }

        测试类

publicclass FanXinZDYTest {

  publicstaticvoid main(String[] args) {

     FanXinZDY<String> jt = new FanXinZDY<String>();//指定了泛型是String类型

     String[] arr = new String[3];

     arr[0] = "李四";

     arr[1] = "王能";

     arr[2] = "李把";

     jt.setArr(arr);

     String str = jt.getByIndex(2);

     System.out.println(str);

  }

}

8.增强的for循环

语法    for( 数据类型 变量: 集合){   }-------这种for循环是有并发问题存在的[缺点]

for (String string : arr) {

       System.out.println(string);

     }

9.并发问题

并发问题就是要考虑线程的安全,比如一个索引在3的集合,同时有两个人在操作,那么这就是不安全的,存在高并发的问题

10.set集合和子类HashSet

HashSet集合是无序的, HashSet集合的元素是不能重复的, HashSet允许有null,只能有一个null

判断两个对象是否相等,必须重写equals和hashCode方法,这两个方法都符合相等的条件才认为是相等的两个对象

LinkedHashSet的方法是继承HashSet的, LinkedHashSet是有顺序的,线程不是安全的,栈,队列操作

TreeSet可以按照元素的自然顺序进行对元素自动排序,因为他实现了Comparable<>的Comparto方法,线程不是安全的,不允许null存在

排序-------------类必须实现一个接口Comparable<>

动态可变参数

       定义语法

       修饰符 返回值类型  方法名(数据类型。。。变量){    }例如 public int add(int 。。。p){}----代表p参数是一个int类型的数组

Arrays工具类

数组的工具类,这里的方法都是静态的-----------此类方法直接查询帮助文档

asList把一个数组转换成list集合,从数组转换过来的东西不允许添加,删除操作,允许修改

集合工具类

Collection和Collections的区别

        Collection是集合的接口,而Collections是操作集合的工具类

Map集合---util包下,键值对的集合的接口抽象

Map的特点

1.    数据成对出现

2.    数据的键是惟一的

3.    一个键智能对应一个值

4.    值可以重复

5.    键允许有一个为空,值可以多个是空

HashMap<K,V>---存储的是键值对,可以通过键取值,键不可以重复,一个键映射一个值,允许一个键是null

        HashMap<K,V>的特点

1.    HashMap是map的实现类

2.    允许多个null和一个null键

3.    Hashmap中的元素没有顺序

4.    Hashmap不是线程安全的

TreeMap------treeMap可以支持Map排序,该映射根据其键的自然顺序进行排序,或者根据创建映射是提供的Comparator进行排序,具体取决于使用的构造方法,treeMap的key不能为空,值可以为空,线程不是安全的(如果要按照自己的意愿进行排序,那就要实现Comparable<>接口,实现他的Comparto方法,进行重写)

HashTable-----任何非 null 对象都可以用作键或值

        HashTable的特点

1.    Hashtable是map的实现类

2.    不允许bull值和bull键

3.    HashTable中的元素没有顺序

4.    HashTable是线程安全的

 

LinkedHashMap

        LinkedHashMap的特点

1.    LinkedHashMap是map的实现类

2.    允许多个null值和一个null键

3.    LinkedHashMap是有顺序的

4.    LinkedHashMap不是线程安全的

 

 

Collection接口下有list和set集合

Map集合和Collection集合的区别

1.    Map集合是键值对的集合,Collection是单一的出现的数据的集合

2.    Map的键是惟一的,而Collection的自接口list集合中的元素是可以重复的,set是惟一的

3.    Map是夫妻对,Collection是光棍

11.文件(file)

       我们操作系统中的所有东西都是文件

File查看帮助文档

删除目录的时间如果目录是非空的,就会删不了

创建文件的时间带有盘符的都是绝对路劲

不指定盘符创建的文件都是相对路劲的,就在项目文件夹下面

删除文件也分为相对路径和绝对路径

文件的判断-----是否是文件夹,是否是文件,是否是相对路劲,是否是绝对路径,文件是否存在,文件是否可读等等

文件的获取

        一般都是get方法

        获得子文件----差帮助文档

遍历文件夹------递归(方法自身调用自身)递归一定有调处条件

        阶乘

publicstaticvoid main(String[] args) {

     int a = DemoDGUI.fn(5);

     System.out.println(a);

  }

  //阶乘

  publicstaticint fn(int n){

     if(n >= 2){

       //对方法自身的调用

       return n*fn(n-1);

     }

     return 1;

  }

        递归查询所有文件夹所有的文件

publicstaticintlevel = 1;//定义文件夹层数

  publicstaticvoid main(String[] args) {

    

     File file = new File("F:");

     printFile(file);

    

  }

  publicstaticvoid printFile(File file){

     //判断文件是否是文件

     if(!file.isDirectory()){

       return;//程序结束

     }

     if(!file.exists()){//文件是否存在

       return;

     }

     level++;

     //遍历文件

     File[] files = file.listFiles();

     for (File file1 : files) {

       for(int i=0;i<level;i++){//打印缩进空格,让文件父子目录有层次感

         System.err.print("\t");

       }

       System.out.println(file1);

       if(file1.isDirectory()){

         printFile(file1);

       }

     }

     level--;

  }

        删除某一个文件夹下面的全部文件

publicstaticvoid main(String[] args) {

    

     File file = new File("");

     deleteFile(file);

    

  }

  publicstaticvoid deleteFile(File file){

     //判断文件是否是文件

     if(!file.isDirectory()){

       return;//程序结束

     }

     if(!file.exists()){//文件是否存在

       return;

     }

     //遍历文件

     File[] files = file.listFiles();

     for (File file1 : files) {

       if(file1.isFile()){

         file1.delete();//删除问价

       }else{

         //如果是文件夹就继续遍历

         deleteFile(file1);

       }

     }

  }

12..io流概述

IO(input output)输入和输出,指的是某个设备或环境进行数据的输入或者输出,例如键盘的输入,在比如显示器就是输出设备,输出图像

IO流在java中从输入和角度分类—

1.    输入流

从文件中读取文件,或者从键盘输入带护具都是属于输入流

2.    输出流

向文件中写入数据

IO流在java中从数据角度分类

1.    字符流(一个字符由两个字节构成)

文本,我们能读懂的都是字符流

       字符输入流的抽象类----Reader(子类---fileReader)

       字符输出流的抽象类----Writer(子类---fileWriter)

使用字符流想一个文件输出hello

创建文件

                创建输出流对象

                把流指向指定的文件

                释放资源

  实现代码如下

publicstaticvoid main(String[] args) {

     //使用字符流向一个文件输出helloword

     File file = new File("E:/Test.txt");

     Writer writer = null;

     try {

       //创建输出流的对象

       file.createNewFile();

       writer = new FileWriter(file);//多态,匪类的引用指向子类的对象

       writer.write("helloword");

       writer.append("哈哈");

       writer.flush();//清空缓冲区,把内容写到文件中

     } catch (IOException e) {

       e.printStackTrace();

     }finally{//关闭资源

       try {

         writer.close();

       } catch (IOException e) {

         e.printStackTrace();

       }

     }

  }

循环写入大量的文件

publicstaticvoid main(String[] args) {

     //向一个文件写100helloword

     FileWriter fw = null;

     try {

       fw = new FileWriter("E:/Test.txt");

       for(int i=0;i<100;i++){

         fw.write("helloword");

         fw.append("helloword");

         if(i ==0){

            fw.flush();

         }

       }

       fw.flush();

     } catch (IOException e) {

       e.printStackTrace();

     }finally{

       try {

         fw.close();

       } catch (IOException e) {

         e.printStackTrace();

       }

     }

  }

\n\r是windows系统的换行

\n是linux系统的的换行

\r是max系统的换行

FileWriter的5中写入方法

      

 void

write(char[] cbuf)           写入字符数组。

abstract  void

write(char[] cbuf, int off, int len)           写入字符数组的某一部分。

 void

write(int c)           写入单个字符。

 void

write(String str)           写入字符串。

 void

write(String str, int off, int len)           写入字符串的某一部分。

FileReader输入流

       FileReader的爷爷类是Reader

读取问价Test.txt,打印到控制台

publicstaticvoid main(String[] args) {

     readerFiler();

  }

  publicstaticvoid readerFiler(){

     FileReader fr = null;

     try {

       fr = new FileReader("E:/Test.txt");

       int i=0;

       while((i=fr.read())!=-1){//没有字符的话会返回-1

         System.out.print((char)fr.read());

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       if(fr!=null){

         try {

            fr.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

       }

     }

  }

字符输入流的读取方式

      

 int

read()           读取单个字符。

 int

read(char[] cbuf)           将字符读入数组。

abstract  int

read(char[] cbuf, int off, int len)           将字符读入数组的某一部分。

 int

read(CharBuffer target)           试图将字符读入指定的字符缓冲区。

使用字符流做文本文件的复制

       范例---把一个java文件拷贝到项目根目录

1.    创建输入流的对象

2.    创建输出流的对象

3.    把输入流输入的数据写入输出流中

4.    关闭资源

publicstaticvoid main(String[] args) {

     copy();

  }

  publicstaticvoid copy(){

     FileReader rea = null;

     FileWriter wer = null;

     try {

       rea = new FileReader("E:/Test.txt");//创建文件读取对象

       wer = new FileWriter("Test.txt");//创建文件写入对象--项目文件下

       int num = -1;

       while((num = rea.read()) != -1){

         //写入文件"Test.txt"

         wer.write(num);

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         //先开的后关

         if(wer != null){

            wer.close();

         }

         if(rea != null){

            rea.close();

         }

       } catch (IOException e) {

         e.printStackTrace();

       }

     }

  }

可以用数组的读取方式,用数组读取的话效率会很高

publicstaticvoid main(String[] args) {

     copy1();

  }

/**

   * 用房数组的方式读取,写入

   */

  publicstaticvoid copy1(){

     FileReader rea = null;

     FileWriter wer = null;

     try {

       rea = new FileReader("E:/Test.txt");//创建文件读取对象

       wer = new FileWriter("Test.txt");//创建文件写入对象--项目文件下

       int len = -1;//定义每次读取的长度对象

       char[] chs = newchar[1024];//定义存储读取内容的字符数组

       while((len = rea.read(chs)) != -1){//len不等于-1就一直读取

         //写入文件"Test.txt"

         wer.write(chs,0,len);

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         //先开的后关

         if(wer != null){

            wer.close();

         }

         if(rea != null){

            rea.close();

         }

       } catch (IOException e) {

         e.printStackTrace();

       }

     }

  }

 

 

 

 

 

2.    字节流(一个字节是八个bit)

二进制数据,一般用文本打开后我们看不懂的就是字节流

       字节输入流的超类----Inputstream(子类---FileInputStream)

       字节输出流的超类----outputstream(子类---FileoutputStream)

       

FileOutputStream(File file)           创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

FileOutputStream(File file, boolean append)           创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

FileOutputStream(String name)           创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutputStream(String name, boolean append)           创建一个向具有指定 name 的文件中写入数据的输出文件流。

范例:使用字节流向文件中写入helloword

三种写入文件的方法

void

write(byte[] b)           将 b.length 个字节从指定字节数组写入此文件输出流中。

 void

write(byte[] b, int off, int len)           将指定字节数组中从偏移量 off 开始的 len 个字节写入此文件输出流。

 void

write(int b)           将指定字节写入此文件输出流。

publicstaticvoid main(String[] args) {

     writebyte();

  }

  /**

   * 使用字节流向文件中写入helloword

   */

  publicstaticvoid writebyte(){

     OutputStream op = null;

     try {

       //创建字节输出流的对象

       op = new FileOutputStream("g.txt");

       String str = "helloword";

       byte[] byt = str.getBytes();

       for (int i=0;i<byt.length;i++) {

         op.write(byt);

       }

       op.flush();

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       if(op != null){

         try {

            op.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

       }

     }

  }

字节输入流FileInputStream

字节流做文件的拷贝

publicstaticvoid main(String[] args) {

     CopyDemo();

  }

  /**

   * 字节流拷贝文件

   * 1.创建输入流的对象,创建输出流的对象

   * 2.读取数据写入数据

   * 3.关闭资源

   */

  publicstaticvoid CopyDemo(){

     InputStream in = null;

     OutputStream out = null;

     try {

       in = new FileInputStream("src/iobyte/CopyDemo.java");//创建文件输入流的对象

       out = new FileOutputStream("outputdemo.java");//文件输出流的对象

       byte[] bs = newbyte[1024];

       int len = -1;

       while((len=in.read(bs)) != -1){

         //把字节数组中的数据写入到output.txt文件中

         out.write(bs, 0, len);

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(out != null){

            out.close();

         }

         if(in != null){

            in.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

范例:使用字节流拷贝图片(note---字节流可以拷贝任何的文件,只要填写要拷贝的文件的目录即可)

publicstaticvoid main(String[] args) {

     CopyDemo1();

  }

/**

   * 字节流拷贝文件----图片

   * 1.创建输入流的对象,创建输出流的对象

   * 2.读取数据写入数据

   * 3.关闭资源

   */

  publicstaticvoid CopyDemo1(){

     InputStream in = null;

     OutputStream out = null;

     try {

       in = new FileInputStream("E:/java系列资料/英标/新旧英语国际英标对照表.png");//创建文件输入流的对象

       out = new FileOutputStream("1.png");//文件输出流的对象

       byte[] bs = newbyte[1024];

       int len = -1;

       while((len=in.read(bs)) != -1){

         //把字节数组中的数据写入到output.txt文件中

          out.write(bs, 0, len);

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(out != null){

            out.close();

         }

         if(in != null){

            in.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

 

13.字符流-----BufferedWriter高效缓冲区输出流

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入,可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了

BufferedWriter(Writer out)           创建一个使用默认大小输出缓冲区的缓冲字符输出流。

范例一:使用高效缓冲区流向文件中写入一句话

publicstaticvoid main(String[] args) {

     writer();

  }

  /**

   * 使用高效输出流写入文件

   */

  publicstaticvoid writer(){

     //创建文件输出流

     FileWriter fw = null;

     BufferedWriter bw = null;

     try {

       fw = new FileWriter("d.txt");

       //创建高效缓冲区对象流

       bw = new BufferedWriter(fw);//new FileWriter("d.txt")这样写

       //输出数据

       bw.write("java太好学,简单");

       //清空缓冲区

       bw.flush();

     } catch (IOException e) {

       e.printStackTrace();

     }finally{

       if(bw != null){

         try {

            //关闭缓冲区的流就会自动关闭FileWriter

            bw.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

       }

     }

  }

 

14. 字符流-----BufferedReader高效缓冲输入流

从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取,可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了

BufferedReader(Reader in)           创建一个使用默认大小输入缓冲区的缓冲字符输入流。

范例:使用高效缓冲区流读取文件

publicstaticvoid main(String[] args) {

     reader();

  }

  /**

   *

   */

  publicstaticvoid reader(){

     //创建文件输出流

     FileReader fw = null;

     BufferedReader bw = null;

     try {

       fw = new FileReader("d.txt");

       //创建高效缓冲区对象流

       bw = new BufferedReader(fw);//new FileWriter("d.txt")这样写

       int num = -1;

       while((num = bw.read()) != -1){

         System.out.print((char)num);

       }

     } catch (IOException e) {

       e.printStackTrace();

     }finally{

       if(bw != null){

         try {

           //关闭缓冲区的流就会自动关闭FileWriter

            bw.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

       }

     }

  }

范例:通过数组的方式读取(推荐使用数组的方式读取文件)

publicstaticvoid main(String[] args) {

     readershuzu();

  }

  /**

   *

   */

  publicstaticvoid readershuzu(){

     //创建文件输出流

     FileReader fw = null;

     BufferedReader bw = null;

     try {

       fw = new FileReader("d.txt");

       //创建高效缓冲区对象流

       bw = new BufferedReader(fw);//new FileWriter("d.txt")这样写

       char[] chs = newchar[1024];

       int len = -1;

       while((len = bw.read(chs)) != -1){

         System.out.print(new String(chs,0,len));

       }

     } catch (IOException e) {

       e.printStackTrace();

     }finally{

       if(bw != null){

         try {

            //关闭缓冲区的流就会自动关闭FileWriter

            bw.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

       }

     }

  }

范例:使用字节流从键盘录入学生休息写入文件

package bufferwrite;

 

publicclass Student implements Comparable<Student>{

  private String name;

  private Integer age;

 

  public String getName() {

     returnname;

  }

 

  publicvoid setName(String name) {

     this.name = name;

  }

 

  public Integer getAge() {

     returnage;

  }

 

  publicvoid setAge(Integer age) {

     this.age = age;

  }

 

  @Override

  publicint compareTo(Student o) {

     int num = this.age - o.getAge();

     if(num==0){

       num = this.name.compareTo(o.getName());

     }

     return num;

  }

 

}

测试类

publicstaticvoid main(String[] args) {

     //定义学生的集合

     TreeSet<Student> st = new TreeSet<Student>();

     Scanner input = new Scanner(System.in);

     System.out.println("请输入您要录入几个学生");

     int count = input.nextInt();

     for(int i=1;i<count;i++){

       input = new Scanner(System.in);

       System.out.println("请输入"+i+"学生的姓名");

       String sname = input.nextLine();

       System.err.println("请输入"+i+"学生的年龄");

       int sage = input.nextInt();

      

       Student s = new Student();

       s.setName(sname);

       s.setAge(sage);

       //把学生加入到集合中

       st.add(s);

     }

     BufferedWriter bw = null;

     try {

       //定义高效缓冲区的字符输出流

       bw = new BufferedWriter(new FileWriter("Student.txt"));

       //循环集合

       for (Student s : st) {

         bw.write(s.getName()+"====="+s.getAge());

         bw.newLine();

       }

       bw.flush();

     } catch (IOException e) {

       e.printStackTrace();

     }finally{

       try {

         if(bw != null){

            bw.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

     System.out.println("录入完毕");

  }

 

15.字节流的高效缓冲区

范例:高效缓冲区字节流拷贝文件

publicstaticvoid main(String[] args) {

     BufferCopyDemo();

  }

  /**

   * 使用高效缓冲区拷贝文件

   */

  publicstaticvoid BufferCopyDemo(){

     InputStream in = null;

     OutputStream out = null;

     try {

       //创建高效缓冲区字节流对象

       in = new BufferedInputStream(new FileInputStream("src/iobyte/CopyDemo.java"));

       out = new BufferedOutputStream(new FileOutputStream("outputdemoBuffered.java"));//文件输出流的对象

       byte[] bs = newbyte[1024];

       int len = -1;

       while((len=in.read(bs)) != -1){

         //把字节数组中的数据写入到output.txt文件中

         out.write(bs, 0, len);

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(out != null){

            out.close();

         }

         if(in != null){

            in.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

 

16.高效缓冲区的扩展方法

输出流---

void

newLine()           写入一个行分隔符。

输出流-----

 String

readLine()           读取一个文本行。

范例:使用高效缓冲区的流拷贝文本文件

publicstaticvoid main(String[] args) {

     readerwriter();

  }

  /**

   * 使用高效输出流写入文件

   */

  publicstaticvoid readerwriter(){

     //创建文件输出流

     FileReader fw = null;

     FileWriter wr = null;

     BufferedReader bw = null;

     BufferedWriter br = null;

     try {

       fw = new FileReader("d.txt");

       //创建高效缓冲区对象流

       bw = new BufferedReader(fw);

       wr = new FileWriter("F.txt");

       br = new BufferedWriter(wr);

       String line = null;

       //读取数据并且写到另一个文件中国

       while((line = bw.readLine()) != null){

         br.write(line);

       }

       br.flush();

     } catch (IOException e) {

       e.printStackTrace();

     }finally{

       if(bw != null){

         try {

            //关闭缓冲区的流就会自动关闭FileWriter

            bw.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

       }

    }

  }

输入流的转换----- InputStreamReader类是字节流装换字符流的桥梁(字节装换字符)

范例:把字节流转换高效字符流

publicstaticvoid main(String[] args) {

     InputStream is = System.in;

     //要想使用字符流的高效缓冲区来操作字节流需要装换

     BufferedReader br = new BufferedReader(new InputStreamReader(is));

     //定义要写入的文件流

    BufferedWriter bw = null;

     String line = null;

     try {

       bw = new BufferedWriter(new FileWriter("de.txt"));

       while((line = br.readLine()) != null){

         if("exit".equals(line)){

            break;

         }

         bw.write(line);

         bw.newLine();

         bw.flush();

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(bw != null){

            bw.close();

         }

         if(br != null){

            br.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

 

 

输出流的装换------ OutputStreamWriter 是字符流通向字节流的桥梁

范例:从一个文件中读取内容使用标准字节流来输出到控制太(使用字符串操作)

publicstaticvoid main(String[] args) {

     BufferedReader br = null;

     BufferedWriter bw = null;

     try {

       br = new BufferedReader(new FileReader("de.txt"));

       //创建爱字符流向字节流转换的对象

       bw = new BufferedWriter(new OutputStreamWriter(System.out));

       String line = null;

       while((line = br.readLine()) != null){

         bw.write(line);

         bw.newLine();

       }

       bw.flush();

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(bw != null){

            bw.close();

         }

         if(br != null){

            br.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

打印流概述----只有输出,没有输入

打印流分为字节打印流和字符打印流

类 PrintWriter是字符打印流类

        特点:

               可以打印各种数据类型

               封装了字符流输出流,还可以做字符流和字节流的转换

可以使用自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出新行字符时才完成。这些方法使用平台自有的行分隔符概念,而不是新行字符。

可以直接向文件中写数据

字符流答应范例

publicstaticvoid main(String[] args) {

     PrintWriter pw = null;

     try {

       pw = new PrintWriter("dex.txt");

       pw.print(true);

       pw.print(34d);

       pw.print(45f);

       pw.print("gfsdgsd");

       pw.flush();

     } catch (FileNotFoundException e) {

       e.printStackTrace();

     }finally{

       try {

         if(pw != null){

            pw.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

 

类 PrintStream是字节打印流类

范例:从文件读取数据,并且打印到控制台

publicstaticvoid main(String[] args) {

     BufferedReader br = null;

     PrintWriter pw = null;

     try {

       br = new BufferedReader(new FileReader("de.txt"));

       pw = new PrintWriter(System.out,true);//true代表自动刷新

       String line = null;

       while((line = br.readLine()) != null){

         pw.println(line);

         //pw.flush();

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(pw != null){

            pw.close();

         }

         if(br != null){

            br.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

范例:使用打印流复制文本文件

publicstaticvoid main(String[] args) {

     BufferedReader br = null;

     PrintWriter pw = null;

     try {

       br = new BufferedReader(new FileReader("de.txt"));

       pw = new PrintWriter(new FileWriter("de1.txt"));

       String line = null;

       while((line = br.readLine()) != null){

         pw.write(line+"\n\r");

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(pw != null){

            pw.close();

         }

         if(br != null){

            br.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

17.属性集合properties

范例读取文件

publicstaticvoid main(String[] args) {

     Properties prop = new Properties();

     FileReader fr = null;

     try {

       fr = new FileReader("prop.txt");

       //把字符流数据独到prop对象中

       prop.load(fr);

       String name = prop.getProperty("name");

       String age = prop.getProperty("age");

       String height = prop.getProperty("height");

       System.err.println(name+"\n"+age+"\n"+height);

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(fr !=null){

            fr.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

工作中的应用范例

在src下创建prop.properties属性文件,代码如下

读取文件

publicstaticvoid main(String[] args) {

     Properties prop = new Properties();

     FileReader fr = null;

     try {

       fr = new FileReader("src/prop.properties");

       //把字符流数据独到prop对象中

       prop.load(fr);

       String name = prop.getProperty("name");

       String age = prop.getProperty("age");

       String height = prop.getProperty("height");

       System.err.println(name+"\n"+age+"\n"+height);

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(fr !=null){

            fr.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

给文件设置值,存储值

publicstaticvoid main(String[] args) {

     Properties prop = new Properties();

     prop.setProperty("name","李四");

     prop.setProperty("age","24");

     prop.setProperty("sex","");

     FileWriter fw = null;

     try {

       fw = new FileWriter("prop1.properties");

       prop.store(fw, null);

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(fw != null){

            fw.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

18.序列化流---对象流

如果想要序列化某个对象,那么这个对象所对应的类必须实现Serializable接口,类通过实现 java.io.Serializable 接口以启用其序列化功能

把对象以流的方式存储在硬盘上或者数据库中的过程就是写序列化流

序列化流

        对象输出流-- ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。

       

构造方法摘要

 

ObjectInputStream(InputStream in)           创建从指定 InputStream 读取的 ObjectInputStream。

 

        对象输入流-- ObjectInputStream 对以前使用ObjectOutputStream 写入的基本数据和对象进行反序列化。

 

构造方法摘要

 

ObjectInputStream(InputStream in)           创建从指定 InputStream 读取的 ObjectInputStream。

 

       

序列化和反序列化代码示例---在序列化的过程中要手动指定要序列化的类的SerialVersionUID,这样可以在类改变后依然可以反序列化,负责会报错

实体类

package demo.seril;

 

import java.io.Serializable;

 

publicclass Person implements Serializable{

 

  /**

   * 给类一个指定的序列化版本的id,如果这个类发生了变化,不会影响反序列化

   */

  privatestaticfinallongserialVersionUID = 1032331381429540769L;

 

 

 

  private String name;

  privateintage;

  public String getName() {

     returnname;

  }

  publicvoid setName(String name) {

     this.name = name;

  }

  publicint getAge() {

     returnage;

  }

  publicvoid setAge(int age) {

     this.age = age;

  }

  @Override

  public String toString() {

     return"Person [name=" + name + ", age=" + age + "]";

  }

}

 

序列化方法和反序列化方法测试类

package demo.seril;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

 

publicclass SerilDemo {

  publicstaticvoid main(String[] args) {

     //java.io.NotSerializableException:类没有实现Serializable接口异常

     //java.io.InvalidClassException:非法类异常

     //writeObject();

     readObject();

    

  }

  /**

   * 序列化在文件中写入一个对象

   */

  publicstaticvoid writeObject(){

     ObjectOutputStream oos = null;

     try {

       //创建序列化的流

       oos = new ObjectOutputStream(new FileOutputStream("person.txt"));

       Person p =new Person();

       p.setName("李四");

       p.setAge(20);

       //调用序列化流的写入方法

       oos.writeObject(p);

     } catch (FileNotFoundException e) {

       e.printStackTrace();

     } catch (IOException e) {

       e.printStackTrace();

     }finally{

       try {

         if(oos != null){

            oos.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

  /**

   * 反序列化,把对象读取出来

   */

  publicstaticvoid readObject(){

     ObjectInputStream oos = null;

     try {

       //创建序列化的流

       oos = new ObjectInputStream(new FileInputStream("person.txt"));

       //从反序列画的流中读取数据

       Object obj = oos.readObject();

       Person p = (Person) obj;

       System.out.println(p);

     } catch (FileNotFoundException e) {

       e.printStackTrace();

     } catch (IOException e) {

       e.printStackTrace();

     }catch (ClassNotFoundException e){

       e.printStackTrace();

     }finally{

       try {

         if(oos != null){

            oos.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

 

}

19.集合序列化----序列化多个对象

代码示例

实体类

package demo.seril;

 

import java.io.Serializable;

 

publicclass Person implements Serializable{

 

  /**

   * 给类一个指定的序列化版本的id,如果这个类发生了变化,不会影响反序列化

   */

  privatestaticfinallongserialVersionUID = 1032331381429540769L;

 

 

 

  private String name;

  privateintage;

  public String getName() {

     returnname;

  }

  publicvoid setName(String name) {

     this.name = name;

  }

  publicint getAge() {

     returnage;

  }

  publicvoid setAge(int age) {

     this.age = age;

  }

  @Override

  public String toString() {

     return"Person [name=" + name + ", age=" + age + "]";

  }

}

 

测试类

package demo.seril;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.util.ArrayList;

 

public class SerilDemo1 {

       public static void main(String[] args) {

              //EOFException:解决这个异常就要用集合存储数据,然后再把集合通过系列化写入文件中

              //writeObject();

              readObject();

             

       }

       /**

        * 序列化在文件中写入多个对象

        */

       public static void writeObject(){

              ObjectOutputStream oos = null;

              try {

                     //创建序列化的流

                     oos = new ObjectOutputStream(new FileOutputStream("person.txt"));

                     //Arraylist是实现了Serializable接口的

                     ArrayList<Person> al = new ArrayList<Person>();

                    

                     Person p =new Person();

                     p.setName("李四");

                     p.setAge(20);

                    

                     Person p1 =new Person();

                     p1.setName("花花");

                     p1.setAge(21);

                    

                     Person p2 =new Person();

                     p2.setName("流露");

                     p2.setAge(24);

                     al.add(p);

                     al.add(p1);

                     al.add(p2);

                     //调用序列化流的写入方法把集合写进去

                     oos.writeObject(al);

              } catch (FileNotFoundException e) {

                     e.printStackTrace();

              } catch (IOException e) {

                     e.printStackTrace();

              }finally{

                     try {

                            if(oos != null){

                                   oos.close();

                            }

                     } catch (Exception e2) {

                            e2.printStackTrace();

                     }

              }

       }

       /**

        * 反序列化,把多个对象读取出来

        */

       public static void readObject(){

              ObjectInputStream oos = null;

              try {

                     //创建序列化的流

                     oos = new ObjectInputStream(new FileInputStream("person.txt"));

                     //从反序列画的流中读取数据

                     Object obj = oos.readObject();

                     ArrayList<Person> al=(ArrayList<Person>) obj;

                     for (Person per : al) {

                            System.err.println(per);

                     }

              } catch (FileNotFoundException e) {

                     e.printStackTrace();

              } catch (IOException e) {

                     e.printStackTrace();

              }catch (ClassNotFoundException e){

                     e.printStackTrace();

              }finally{

                     try {

                            if(oos != null){

                                   oos.close();

                            }

                     } catch (Exception e2) {

                            e2.printStackTrace();

                     }

              }

       }

      

}

 

20.字符集编码

存储

在计算机中存储字符都是存储的字符所对应的数值以二进制的形式

展示

去相关的编码表中去查找该值(存储的值)所对应的字符

编码guize

        ASCII码表----用七位来表示(7个bit)

        ISO-8859-1:拉丁码表-----用8个bit表示

        Gb2312:简体中文编码(国标码)

        GBK:在gb2312做了增强

        Gb18030:对gbk做了增强

        BIG5:支持繁体,简体也支持

        Unicode:支持多种国家语言,这是国际标准,用两个字节来存储,不管是什么字符都用两个字节,这样会出现浪费

        Utf-8:支持多种国家语言,这对不同的字符范围给出不同的字节表示,中文用3个字符存储,

范例:使用GBK的编码方式来写入文件--------读和写的字符编码要一致,用什么编码就要用是吗解码

package demo.charset;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.io.UnsupportedEncodingException;

 

publicclass CharsetDemo {

  publicstaticvoid main(String[] args) {

     //printCharSet();

     readCharSet();

     //Note----读和写的字符编码要一致,用什么编码就要用是吗解码

  }

  publicstaticvoid printCharSet(){

     OutputStreamWriter ow = null;

     try {

       ow = new OutputStreamWriter(new FileOutputStream("test.txt"),"GBK");

       ow.write("中国");

     } catch (UnsupportedEncodingException e) {

       e.printStackTrace();

     } catch (FileNotFoundException e) {

       e.printStackTrace();

     }catch (IOException e){

       e.printStackTrace();

     }finally{

       try {

         if(ow != null){

            ow.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

  publicstaticvoid readCharSet(){

     InputStreamReader ow = null;

     try {

       ow = new InputStreamReader(new FileInputStream("test.txt"),"GBK");

       char[] chs = newchar[1024];

       int len = ow.read(chs);

       System.out.println(new String(chs,0,len));

     } catch (UnsupportedEncodingException e) {

       e.printStackTrace();

     } catch (FileNotFoundException e) {

       e.printStackTrace();

     }catch (IOException e){

       e.printStackTrace();

     }finally{

       try {

         if(ow != null){

            ow.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

}

 

字符串的编码问题

package demo.charset;

 

import java.io.UnsupportedEncodingException;

 

publicclass CharsetDemo {

  publicstaticvoid main(String[] args) throws UnsupportedEncodingException {

     String str = "中国";

     byte[] bsgbk = str.getBytes();//采用的是默认编码

     byte[] bstf8 = str.getBytes("UTF-8");

    

     printByte(bsgbk);

     System.err.println(new String(bsgbk));

    

     printByte(bstf8);

     System.err.print(new String(bstf8,"utf-8"));//utf8指定字符编码值,如果不指定就会乱码

  }

  publicstaticvoid printByte(byte[] bs){

     for (byte b : bs) {

       System.err.print(b+"   ");

     }

  }

}

 

运行结果

 

 

21线程.

进程:计算机中特定功能的程序在数据上的一次运行

线程:线程低进程的一个单元

多线程指的就是一个进程里面有多个线程(程序)在运行

JVM是多线程的,在我们运行JVM的时间,后台会运行垃圾回收的线程,来清理没有被引用的对象

进程

                            

                                                  进程

 

 

 

 

线程1

线程2

 

 

 

 

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:

线程创建的第一种方式-----线程启动的时间使用线程的start()方法

        创建线程代码示例

package com.thread;

 

publicclass ThreadDemo extends Thread{

  /**

   * 线程的执行体

   */

  @Override

  publicvoid run() {

     for(int i=0;i<50;i++){

       System.err.println(this.getName()+"hello"+i);

     }

  }

}

       

 

测试线程的方法

package com.thread;

 

publicclass ThreadTest {

  publicstaticvoid main(String[] args) {

     //创建线程的实例对象

     ThreadDemo thread = new ThreadDemo();

     ThreadDemo thread1 = new ThreadDemo();

     //启动线程, 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

     thread.start();

     thread1.start();

  }

}

线程的第二种实现方式------ Runnable接口

Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法

        线程类

package com.thread;

 

publicclass ThreadDemo1 implements Runnable{

 

  @Override

  publicvoid run() {

     for(int i=0;i<50;i++){

       //输出线程的名字

       System.err.println(Thread.currentThread().getName()+"hello"+i);

     }

  }

}

        线程测试类

package com.thread;

 

publicclass ThreadTest1 {

  publicstaticvoid main(String[] args) {

     //创建两个线程

     ThreadDemo1 thread = new ThreadDemo1();

     Thread t1 = new Thread(thread,"线程1");

    

    

     ThreadDemo1 thread1 = new ThreadDemo1();

     Thread t11 = new Thread(thread1,"线程2");

    

     //启动线程

     t1.start();

     t11.start();

  }

}

CPU

线程的执行原理

线程不能同时拥有CPU

线程1,2,3他们是不断抢占CPU资源,得到执行

进程

线程1

线程2

线程3

 

 

线程的并发执行是通过多个线程不断的切换CPU的资源,这个速度非常快,我们感知不到,我们能感知到的就是三个线程在并发执行

线程生命周期

1.    新建状态-----线程被new出来

2.    准备状态----线程具有执行的资格,start()方法,但是没有执行权利,

3.    运行状态----具备执行的资格和具备执行的权利

4.    阻塞状态-----线程的休眠sleep(),线程的等待wait(),没有执行的资格和执行的权利

5.    销毁-----run()方法结束,线程销毁(stop()方法可以让线程销毁)

并发安全性问题----互联网的项目中存在着大量的并发案例---比如买火车票

范例:火车站有100张票,4个窗口同时买票

        分析:4个窗口4个线程同时在运行,100张票是4个线程的共享资源

采用继承Thread实现

Synchronized解决并发安全问题-------同步锁

针对线程的安全性为题,我们需要使用同步锁,共享资源智能同时一个人进行访问

        语法:synchronized(锁对象){

     //操作共享资源的代码

同步代码加在什么地方

1.    代码被多个线程访问

2.    代码中有共享的数据

3.    共享的数据被多条语句操作

Synchronized锁对象剖析

       Synchronized同步代码块的锁对象可以是任意类对象(线程的实现方式是使用继承与Thread),这个对象必须是线程类共享的(静态的)

Synchronized是可以加在方法上的,如果是静态方法synchronized的对象就是类的对象,

   继承Thread类实现

模拟买票窗口线程-----创建线程类

package com.tickets;

/**

 * 模拟买票窗口

 * @author Administrator

 *

 */

publicclass SaleTicket extends Thread{

  private String name;

 

  public SaleTicket(String name) {

     super(name);

  }

  //100张票是对象共享的数据

  privatestaticinttickets = 100;

  //同步锁对象

  privatestatic Object obj = new Object();

  /**

   * 静态方法的synchronized锁是当前的类对象

   */

  @Override

  publicvoid run() {

     while(true){

       //同步代码块

       synchronized (obj) {

         if(tickets > 0){

            try {

              Thread.sleep(1000);

            } catch (InterruptedException e) {

              e.printStackTrace();

            }

            System.err.println(this.getName()+"正在卖第"+tickets--+"");

         }else{

            System.err.println("票已经卖完");

            break;

         }

       }

     }

  }

}

线程的测试类

package com.tickets;

 

publicclass TicketTest {

  publicstaticvoid main(String[] args) {

     SaleTicket st1 = new SaleTicket("窗口1");

     SaleTicket st2 = new SaleTicket("窗口2");

     SaleTicket st3 = new SaleTicket("窗口3");

     SaleTicket st4 = new SaleTicket("窗口4");

    

    

     st1.start();

     st2.start();

     st3.start();

     st4.start();

  }

}

 

 

线程休眠方法---sellp()方法

     线程的休眠如果是在同步代码块中执行的,不会让出锁对象

线程之间的通信

   生产者与消费者-----生产线程和消费线程(他们之间是互相通知的,生产者生产完了就会通知消费线程,消费线程消费完了就通知生产者去生产)

线程之间通信代码实现---线程之间的通信一定要有同步代码块synchronized,一定要有waitnotif,而且二者一定是成对出现的,生产者和消费者一定是在死循环之中(whilr(true)

生产的实物---水果

package cn.tx;

 

publicclass Fruit {

  private String name;

 

  privatebooleanisExsit;

 

  public String getName() {

     returnname;

  }

 

  publicvoid setName(String name) {

     this.name = name;

  }

 

  publicboolean isExsit() {

     returnisExsit;

  }

 

  publicvoid setExsit(boolean isExsit) {

     this.isExsit = isExsit;

  }

}

 

生产者线程----生产线程

package cn.tx;

 

/**

 * 生产线程

 * @author Administrator

 *

 */

publicclass ProductFruit implements Runnable{

  private Fruit fruit;

 

 

 

  public ProductFruit(Fruit fruit) {

     super();

     this.fruit = fruit;

  }

 

 

 

  @Override

  publicvoid run() {

     while(true){

     //有共享的数据,多个线程操作共享数据,必须使用锁

       synchronized (fruit) {

         //如果水已经存在,生产者就不会在生产,等待消费者买走

         if(fruit.isExsit()){

            //把线程挂起,阻塞状态

            try {

              //当前伤残水果的线程被挂起

              fruit.wait();

            } catch (InterruptedException e) {

              e.printStackTrace();

            }

         }

         try {

            Thread.sleep(100);

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

         System.out.println(fruit.getName()+"水果被生产出来");

         //把水果的状态变为存在

         fruit.setExsit(true);

         //唤醒等待买水果的线程

         fruit.notify();

       }

     }

  }

}

 

消费线程----消费水果

package cn.tx;

/**

 * 消费线程

 * @author Administrator

 *

 */

publicclass BuyFruit implements Runnable{

  private Fruit fruit;

 

  public BuyFruit(Fruit fruit) {

     super();

     this.fruit = fruit;

  }

 

  @Override

  publicvoid run() {

     //有共享的数据,多个线程操作共享数据,必须使用锁

     synchronized (fruit) {

       if(!fruit.isExsit()){//如果现在没有水果

         try {

            fruit.wait();

         } catch (InterruptedException e) {

            e.printStackTrace();

         }

       }

       try {

         Thread.sleep(100);

       } catch (InterruptedException e) {

         e.printStackTrace();

       }

       System.out.println(fruit.getName()+"水果被买走");

       //水果被买走就把状态设置为false

       fruit.setExsit(false);

       //唤醒生产者线程

       fruit.notify();

     }

    

  }

}

 

线程的测试类

package cn.tx;

 

publicclass Client {

  publicstaticvoid main(String[] args) {

     Fruit fruit = new Fruit();

     fruit.setName("苹果");

     fruit.setExsit(false);

    

    

    

     ProductFruit pf = new ProductFruit(fruit);

     BuyFruit bf = new BuyFruit(fruit);

    

    

     Thread t1 = new Thread(pf);

     Thread t2 = new Thread(bf);

    

    

     t1.start();

     t2.start();

    

  }

}

 

线程优先级

 

我们可以通过setPriority(int newpriority)来设置线程的优先级,但是优先级并不是绝对的,只是相对来说比其他的线程得到cpu的资源机会多一些

示例代码

线程类

package com.pro;

 

publicclass PrioThread extends Thread{

 

  @Override

  publicvoid run() {

     for(int i=0;i<50;i++){

       System.out.println(this.getName()+"正在运行"+i);

     }

  }

}

线程优先级测试类

package com.pro;

 

publicclass PrioThreadTest {

  publicstaticvoid main(String[] args) {

     PrioThread pt1 = new PrioThread();

     PrioThread pt2 = new PrioThread();

     PrioThread pt3 = new PrioThread();

     //线程的优先级,默认的

     System.out.println(pt1.getPriority());

     System.out.println(pt2.getPriority());

     System.out.println(pt3.getPriority());

     //设置线程的优先级

     pt1.setPriority(10);

     /*pt1.start();

     pt2.start();

     pt3.start();*/

  }

}

加入线程和等待线程

 void

join()           等待该线程终止。

加入线程----线程类

package com.pro.join;

 

publicclass JoinThread extends Thread{

 

  @Override

  publicvoid run() {

     for(int i=0;i<50;i++){

       System.out.println(this.getName()+"正在运行"+i);

     }

  }

}

 

加入线程的测试类

package com.pro.join;

 

publicclass JoinThreadTest {

  publicstaticvoid main(String[] args) {

     JoinThread pt1 = new JoinThread();

     JoinThread pt2 = new JoinThread();

     JoinThread pt3 = new JoinThread();

     //线程的优先级,默认的

     System.out.println(pt1.getPriority());

     System.out.println(pt2.getPriority());

     System.out.println(pt3.getPriority());

     //设置线程的优先级

     pt1.setPriority(10);

     //设置加入线程,就是让谁先执行,如果调用线程的join方法,此线程会优先执行

     try {

       pt2.join();

     } catch (InterruptedException e) {

       e.printStackTrace();

     }

    

     pt1.start();

     pt2.start();

     pt3.start();

  }

}

 

等待线程

static void

yield()           暂停当前正在执行的线程对象,并执行其他线程。

当前的线程从运行阶段回到就绪阶段,目的是把cpu的资源让给其他的线程,让线程之间的执行比较均匀

等待线程的线程类

package com.pro.yield;

 

publicclass YieldThread extends Thread{

 

  @Override

  publicvoid run() {

     for(int i=0;i<50;i++){

       System.out.println(this.getName()+"正在运行"+i);

       //运行一次就把cpu让给其他线程执行,当前的线程回到就绪的状态

       Thread.yield();

     }

  }

}

等待线程的测试类

package com.pro.yield;

 

publicclass YieldThreadTest {

  publicstaticvoid main(String[] args) {

     YieldThread pt1 = new YieldThread();

     YieldThread pt2 = new YieldThread();

     YieldThread pt3 = new YieldThread();

    

     pt1.start();

     pt2.start();

     pt3.start();

  }

}

守护线程

 void

setDaemon(boolean on)           将该线程标记为守护线程或用户线程。

守护线程会随着主线程的结束而结束

守护线程的线程类

package com.pro.daemn;

 

publicclass DaemnThread extends Thread {

 

  @Override

  publicvoid run() {

     for (int i = 0; i < 50; i++) {

       System.out.println(this.getName() + "正在运行" + i);

      

     }

  }

}

守护线程的测试类

package com.pro.daemn;

 

publicclass DaemnThreadTest {

  publicstaticvoid main(String[] args) {

     DaemnThread pt1 = new DaemnThread();

     DaemnThread pt2 = new DaemnThread();

     pt1.setDaemon(true);

     pt2.setDaemon(true);

     pt1.start();

     pt2.start();

    

     //现在main方法是主线程

     for(int i=0;i<10;i++){

       System.out.println(Thread.currentThread().getName()+"主线程正在运行"+i);

     }

  }

}

 

线程死锁

在做线程开发的时间要避免出现死锁

线程死锁-----

package cn.lock;

 

publicclass Lock {

  /**

   * 两把锁

   */

  static Object lock1 = new Object();

  static Object lock2 = new Object();

 

}

线程死锁----线程死锁示例

package cn.lock;

 

publicclass DieLockDemo implements Runnable{

  /**

   * 示例线程的死锁

   */

  privatebooleanflag;

  public DieLockDemo(boolean flag) {

     super();

     this.flag = flag;

  }

  @Override

  publicvoid run() {

     if(flag){

       synchronized (Lock.lock1) {

         System.out.println("线程1拿到第一把锁");

         synchronized (Lock.lock2) {

            System.out.println("线程2拿到第二把锁");

         }

       }

     }else{

       synchronized (Lock.lock2) {

         System.out.println("线程2拿到第二把锁");

         synchronized (Lock.lock1) {

            System.out.println("线程2拿到第一把锁");

         }

       }

     }

  }

}

线程死锁的测试类

package cn.lock;

 

publicclass DieLockTest {

  publicstaticvoid main(String[] args) {

     DieLockDemo dd1 = new DieLockDemo(true);

     DieLockDemo dd2 = new DieLockDemo(false);

    

    

     Thread t1 = new Thread(dd1);

     Thread t2 = new Thread(dd2);

    

     t1.start();

     t2.start();

    

  }

}

22.网络编程

概念---是指将地理位置不同的具有独立功能的多台计算机以及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件以及通信的协议管理下,实现资源共享和信息传递的计算机系统

网络编程---就是用来实现网络互通的不同计算机运行程序之间进行数据的交换编程

   Windows系统下查看ip地址命令-----ipconfig

                 查看两台计算机是否通信-----ping 对方的端口号

常见的两种协议

UDP—-----将数据源和目的地封装到数包中,不需要建立连接,每个数据包的大小限制在64K,因为不建立连接,所以安全性差,速断块

TCP-----建立连接形成传输数据的通道,然后在传输数据,通过三次的握手,完全性高,效率地

网络通信的三要素-----ip,端口,协议

InetAddress--------此类表示互联网协议 (IP) 地址

   用于管理ip的类,没有构造器

1. 单例模式

2. 根据静态的方法来返回该对象

Java.net包下全部是网络编程的东西

static InetAddress

getByName(String host)           在给定主机名的情况下确定主机的 IP 地址。

 String

getCanonicalHostName()           获取此 IP 地址的完全限定域名。

 String

getHostAddress()           返回 IP 地址字符串(以文本表现形式)。

 String

getHostName()           获取此 IP 地址的主机名。

代码示例

package cn.network;

 

import java.net.InetAddress;

import java.net.InterfaceAddress;

import java.net.UnknownHostException;

 

publicclass IPAddressDemo {

  publicstaticvoid main(String[] args) {

     //后去本机的ip

     try {

       InetAddress aa = InetAddress.getLocalHost();

       System.out.println(aa);

       //获得本机ip的字符串

       String ip = aa.getHostAddress();

       System.out.println(ip);

       //获得主机名

       String hostname = aa.getHostName();

       System.out.println(hostname);

       //知道主机名的情况下获取ip地址和主机名

       InetAddress ipname = InetAddress.getByName("V7Y373BF5YBUXJ6");

       System.out.println(ipname);

     } catch (UnknownHostException e) {

       e.printStackTrace();

     }

  }

}

 

UDP的开发步骤

类 DatagramSocket-----发送数据的类

类 DatagramPacket-----接受数据的类----此类表示数据报包。

 

Socket---socket是网络编程提供的一种机制,通信的两端都要有socket,网络通信其实就是socket间的通信,数据在两个socket间的io流上通信

UDP开发步骤代码示例

服务器端

package cn.network1;

 

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/**

 * 服务器端

 * @author Administrator

 *

 */

publicclass UDPService {

  publicstaticvoid main(String[] args) {

     DatagramSocket ds = null;

     //创建udp服务器端的对象,必须指定端口

     try {

       ds = new DatagramSocket(10000);

       //定义接收数据的字节数组

       byte[] bs = newbyte[1024];

       //定义接收的数据包

       DatagramPacket dp = new DatagramPacket(bs, bs.length);

       System.out.println("服务器端已经启动");

       //接收数据包

       ds.receive(dp);

      

       //获得发送端的ip地址

       InetAddress ia = dp.getAddress();

      

       //获得数据包中的数据

       byte[] bs1 = dp.getData();

       //获得接收数据的长度

       int len = dp.getLength();

       //组装接收的数据

       String data = new String(bs1,0,len);

       System.out.println(ia.getHostAddress()+"接收了"+data);     

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       //关闭服务端对象

       if(ds != null){

         ds.close();

       }

     }

  }

}

发送数据端----客户端

package cn.network1;

 

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

 

/**

 * 客户端

 * @author Administrator

 *

 */

publicclass UDPClient {

  publicstaticvoid main(String[] args) {

     DatagramSocket ds = null;

     //创建客户端的套接字对象

     try {

       ds = new DatagramSocket();

       //指定数据包

       byte[] bs = "您好".getBytes();

       //创建要发送目的地的ip对象

       InetAddress ia =InetAddress.getByName("V7Y373BF5YBUXJ6");

       //组装数据包

       DatagramPacket dp = new DatagramPacket(bs, bs.length,ia,10000);

       //发送数据

       ds.send(dp);

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       if(ds !=null){

         ds.close();

       }

     }

  }

}

UDP从控制台输入数据发送到服务器代码示例

服务器端

package cn.network1;

 

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/**

 * 服务器端

 * @author Administrator

 *

 */

publicclass UDPService {

  publicstaticvoid main(String[] args) {

     DatagramSocket ds = null;

     //创建udp服务器端的对象,必须指定端口

     try {

       ds = new DatagramSocket(10000);

       //定义接收数据的字节数组

       byte[] bs = newbyte[1024];

       System.out.println("服务器端已经启动");

       while(true){

         //定义接收的数据包

         DatagramPacket dp = new DatagramPacket(bs, bs.length);

         //接收数据包

         ds.receive(dp);

        

         //获得发送端的ip地址

         InetAddress ia = dp.getAddress();

        

         //获得数据包中的数据

         byte[] bs1 = dp.getData();

         //获得接收数据的长度

         int len = dp.getLength();

         //组装接收的数据

         String data = new String(bs1,0,len);

         //退出

         if("exit".equals(data)){

            break;

         }

         System.out.println(ia.getHostAddress()+"接收了"+data);

       }     

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       //关闭服务端对象

       if(ds != null){

         ds.close();

       }

     }

  }

}

客户端

package cn.network1;

 

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

 

/**

 * 客户端

 * @author Administrator

 *

 */

publicclass UDPClient {

  publicstaticvoid main(String[] args) {

     BufferedReader br = null;//创建控制台的输入流

     DatagramSocket ds = null;//创建客户端的套接字对象

    

     try {

       br = new BufferedReader(new InputStreamReader(System.in));

       ds = new DatagramSocket();

       while(true){

         //从控制台读取一行

         String line = br.readLine();

         byte[] bs = line.getBytes();

         //创建要发送目的地的ip对象

         InetAddress ia =InetAddress.getByName("V7Y373BF5YBUXJ6");

         //组装数据包

         DatagramPacket dp = new DatagramPacket(bs, bs.length,ia,10000);

         //发送数据

         ds.send(dp);

         //退出程序

         if("exit".equals(line)){

            break;

         }

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       if(ds !=null){

         ds.close();

       }

     }

  }

}

 

UDP简易聊天室代码示例

服务器端1

package cn.network2;

 

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/**

 * 服务器端

 * @author Administrator

 *

 */

public class UDPService implements Runnable{

  private int port;

 

 

  public UDPService(int port) {

     super();

     this.port = port;

  }

 

 

  @Override

  public void run() {

     DatagramSocket ds = null;

     //创建udp服务器端的对象,必须指定端口

     try {

       ds = new DatagramSocket(port);

       //定义接收数据的字节数组

       byte[] bs = new byte[1024];

       System.out.println("服务器端已经启动");

       while(true){

         //定义接收的数据包

         DatagramPacket dp = new DatagramPacket(bs, bs.length);

         //接收数据包

         ds.receive(dp);

        

         //获得发送端的ip地址

         InetAddress ia = dp.getAddress();

        

         //获得数据包中的数据

         byte[] bs1 = dp.getData();

         //获得接收数据的长度

         int len = dp.getLength();

         //组装接收的数据

         String data = new String(bs1,0,len);

         //退出

         if("exit".equals(data)){

            break;

         }

         System.out.println(ia.getHostAddress()+"\r\n"+data);

       }     

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       //关闭服务端对象

       if(ds != null){

         ds.close();

       }

     }

    

  }

}

客户端1

package cn.network2;

 

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

 

/**

 * 客户端

 * @author Administrator

 *

 */

public class UDPClient implements Runnable{

  /**

   * 发送数据目的的ip

   */

  private String ip;

 

  private int port;

 

  public UDPClient(String ip, int port) {

     super();

     this.ip = ip;

     this.port = port;

  }

 

  @Override

  public void run() {

     BufferedReader br = null;//创建控制台的输入流

     DatagramSocket ds = null;//创建客户端的套接字对象

    

     try {

       br = new BufferedReader(new InputStreamReader(System.in));

       ds = new DatagramSocket();

       System.out.println("已经介入"+ip);

       while(true){

         //从控制台读取一行

         String line = br.readLine();

         byte[] bs = line.getBytes();

         //创建要发送目的地的ip对象

         InetAddress ia =InetAddress.getByName(ip);

         //组装数据包

         DatagramPacket dp = new DatagramPacket(bs, bs.length,ia,port);

         //发送数据

         ds.send(dp);

         System.out.println("我说:\r\n"+line);

         //退出程序

         if("exit".equals(line)){

            break;

         }

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       if(ds !=null){

         ds.close();

       }

     }

  }

}

线程聊天室1

/**

 * 聊天室

 * @author Administrator

 *

 */

publicclass CharRoom {

  publicstaticvoid main(String[] args) {

     //创建接收端的线程实现

     UDPClient uc = new UDPClient("192.168.80.1",10001);

     UDPService us = new UDPService(10000);

    

    

     //发送端的线程

     Thread t1 = new Thread(uc);

     //接收端的线程

     Thread t2 = new Thread(us);

     //启动两个线程

     t1.start();

     t2.start();

    

  }

}

服务器2

package cn.network3;

 

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/**

 * 服务器端

 * @author Administrator

 *

 */

public class UDPService1 implements Runnable{

  private int port;

 

 

  public UDPService1(int port) {

     super();

     this.port = port;

  }

 

 

  @Override

  public void run() {

     DatagramSocket ds = null;

     //创建udp服务器端的对象,必须指定端口

     try {

       ds = new DatagramSocket(port);

       //定义接收数据的字节数组

       byte[] bs = new byte[1024];

       System.out.println("服务器端已经启动");

       while(true){

         //定义接收的数据包

         DatagramPacket dp = new DatagramPacket(bs, bs.length);

         //接收数据包

         ds.receive(dp);

        

         //获得发送端的ip地址

         InetAddress ia = dp.getAddress();

        

         //获得数据包中的数据

         byte[] bs1 = dp.getData();

         //获得接收数据的长度

         int len = dp.getLength();

         //组装接收的数据

         String data = new String(bs1,0,len);

         //退出

         if("exit".equals(data)){

            break;

         }

         System.out.println(ia.getHostAddress()+"\r\n"+data);

       }     

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       //关闭服务端对象

       if(ds != null){

         ds.close();

       }

     }

    

  }

}

客户端2

package cn.network3;

 

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

 

/**

 * 客户端

 * @author Administrator

 *

 */

public class UDPClient1 implements Runnable{

  /**

   * 发送数据目的的ip

   */

  private String ip;

 

  private int port;

 

  public UDPClient1(String ip, int port) {

     super();

     this.ip = ip;

     this.port = port;

  }

 

  @Override

  public void run() {

     BufferedReader br = null;//创建控制台的输入流

     DatagramSocket ds = null;//创建客户端的套接字对象

    

     try {

       br = new BufferedReader(new InputStreamReader(System.in));

       ds = new DatagramSocket();

       System.out.println("已经介入"+ip);

       while(true){

         //从控制台读取一行

         String line = br.readLine();

         byte[] bs = line.getBytes();

         //创建要发送目的地的ip对象

         InetAddress ia =InetAddress.getByName(ip);

         //组装数据包

         DatagramPacket dp = new DatagramPacket(bs, bs.length,ia,port);

         //发送数据

         ds.send(dp);

         System.out.println("我说:\r\n"+line);

         //退出程序

         if("exit".equals(line)){

            break;

         }

       }

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       if(ds !=null){

         ds.close();

       }

     }

  }

}

线程聊天室2

package cn.network3;

/**

 * 聊天室

 * @author Administrator

 *

 */

publicclass CharRoom1 {

  publicstaticvoid main(String[] args) {

     //创建接收端的线程实现

     UDPClient1 uc = new UDPClient1("192.168.80.1",10000);

     UDPService1 us = new UDPService1(10001);

    

    

     //发送端的线程

     Thread t1 = new Thread(uc);

     //接收端的线程

     Thread t2 = new Thread(us);

     //启动两个线程

     t1.start();

     t2.start();

    

  }

}

TCP通信

代码示例

文件的横纵转换代码示例

实体类

package cn.pf;

 

publicclass Student implements Comparable<Student>{

 

  private String StuNo;

  private String name;

  private String gender;

  private String age;

  private String top;

  private String weight;

  private String tl;

 

 

 

  public String getStuNo() {

     returnStuNo;

  }

  publicvoid setStuNo(String stuNo) {

     StuNo = stuNo;

  }

  public String getName() {

     returnname;

  }

  publicvoid setName(String name) {

     this.name = name;

  }

  public String getGender() {

     returngender;

  }

  publicvoid setGender(String gender) {

     this.gender = gender;

  }

  public String getAge() {

     returnage;

  }

  publicvoid setAge(String age) {

     this.age = age;

  }

  public String getTop() {

     returntop;

  }

  publicvoid setTop(String top) {

     this.top = top;

  }

  public String getWeight() {

     returnweight;

  }

  publicvoid setWeight(String weight) {

     this.weight = weight;

  }

  public String getTl() {

     returntl;

  }

  publicvoid setTl(String tl) {

     this.tl = tl;

  }

  @Override

  public String toString() {

     return"Student [StuNo=" + StuNo + ", name=" + name + ", gender="

         + gender + ", age=" + age + ", top=" + top + ", weight="

         + weight + ", tl=" + tl + "]";

  }

  @Override

  publicint compareTo(Student o) {

     returnthis.StuNo.compareTo(o.StuNo);

    

  }

}

 

方法以及测试

package cn.pf;

 

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.PrintWriter;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

 

publicclass FileUtil {

  publicstaticvoid main(String[] args) {

     parsfile();

     write();

  }

  //定义存储学生对象的集合

  static List<Student> slist = new ArrayList<Student>();

  /**

   * 解析文件,

   */

  publicstaticvoid parsfile(){

     //定义字符缓冲区

     BufferedReader br = null;

     try {

       br = new BufferedReader(new FileReader("student.txt"));

       //定义是否是第一行的变量

       boolean isFristRow = true;

       //定义存储行的变量

       String line = null;

       while((line = br.readLine()) != null){

         //把每一个行通过空格来切分

         String[] arr = line.split(" ");

         //如果是第一行

         if(isFristRow){

            //遍历第一行的学号,普通for循环

            for (int i=1;i<arr.length;i++) {

              //创建学生对象

              Student s = new Student();

              //把学生加入集合

              slist.add(s);

            }

            isFristRow = false;

         }

         //给学生赋值属性

         setAttr(arr);

       }

       System.out.println(slist);

       System.out.println(slist);

     } catch (Exception e) {

       e.printStackTrace();

     }finally{

       try {

         if(br != null){

            br.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

 

  publicstaticvoid setAttr(String[] arr){

     //获得每一行的头

     String head = arr[0];

     //循环每一个行切分出来的项,从第二项开始

     for(int i=1;i<arr.length;i++){

       //在集合中根据索引获取学生对象

       Student s = slist.get(i-1);

       switch (head) {

         case"学号":

            s.setStuNo(arr[i]);

            break;

         case"姓名":

            s.setName(arr[i]);

            break;

         case"性别":

            s.setGender(arr[i]);

            break;

         case"年龄":

            s.setAge(arr[i]);

            break;

         case"身高":

            s.setTop(arr[i]);

            break;

         case"体重":

            s.setWeight(arr[i]);

            break;

         case"电话":

            s.setTl(arr[i]);

            break;

           

         default:

            break;

       }

     }

  }

 

 

  /**

   * 把集合写入文件

   */

  publicstaticvoid write(){

     //排序

     Collections.sort(slist);

     PrintWriter pw = null;

     try {

       pw = new PrintWriter("studentresult1.txt");

       pw.println("学号\t姓名\t姓名\t年龄\t身高\t体重\t电话");

       for (Student s : slist) {

         pw.println(s.getStuNo()+"\t"+s.getName()+"\t"+s.getGender()+"\t"+s.getAge()+"\t"+s.getTop()+"\t"+s.getWeight()+"\t"+s.getTl());

          pw.flush();

       }

     } catch (FileNotFoundException e) {

       e.printStackTrace();

     }finally{

       try {

         if(pw != null){

            pw.close();

         }

       } catch (Exception e2) {

         e2.printStackTrace();

       }

     }

  }

}

 

转载请注明原文地址: https://www.6miu.com/read-2650050.html

最新回复(0)