JAVA入门学习实例

来源:互联网 发布:上瘾网络剧未剪版 编辑:程序博客网 时间:2024/06/13 23:23

Java面向对象中类与对象的概念和使用

  构造方法的主要作用 一是用来实例化该类。二是 让该类实例化的时候执行哪些方法,初始化哪些属性。当一个类声明了构造函数以后,JVM 是不会再给该类分配默认的构造函数。
构造方法是一种特殊的方法,具有以下特点。
(1)构造方法的方法名必须与类名相同。
(2)构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型。
(3)构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域。
(4)构造方法不能由编程人员调用,而要系统调用。
(5)一个类可以定义多个构造方法,如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码。
(6)构造方法可以重载,以参数的个数,类型,或排列顺序区分

 重载与重写:
  重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,最常见的重载的例子就是类的构造函数
  重写是子类的方法覆盖父类的方法,发生在继承中,要求方法名,参数类型和返回值都相同。被重写的方法不能拥有比父类更严格的权限(public>protected>default>private)
 

package test;class Person{    String name;    int age;    public Person(String name,int age){    //构造方法        this.name=name;        this.age=age;    }    public Person(String name){  //方法重载,对参数类型或个数,权限均无要求        this.name=name;        System.out.println(name);    }    public void tell(){        System.out.println(name +":" + age);    }}public class zlk {  public static void main(String[] args) {    Person p =new Person("zhang",17);    p.tell();  Person q =new Person("Li");  }}

Java面向对象的基本特征之封装性

封装就是隐藏实现细节,将属性私有化,提供公有方法访问私有属性。

package test;class Person{    private String name;    private int age;                //将类的成员变量声明为private    public void setName(String name) {  //通过public的方法对变量进行访问   this.name = name;       //一般定义两个方法实现这两种操作,即:setxx()与getxx()    }    public String getName() {        return name;    }    public void setAge(int age) {        this.age = age;    }    public int getAge() {        return age;    }    public void tell(){        System.out.println(getName() +":" + getAge());    }}public class zlk {  public static void main(String[] args) {    Person p =new Person();    p.setName("Zhang");    p.setAge(17);    p.tell();  }}

Java面向对象基本特征之继承

JAVA只支持单继承,一个类只能有一个父类,同时一个类可以实现多个接口,从而克服单继承的缺点。
子类不能直接访问父类private成员,可用set,get方法;
子对象的实例化过程先调用父类的构造方法,在调用子类的构造方法;
子类重写父类方法之后(方法名称,返回类型,参数都相同),不能拥有比父类更严格的访问权限(public>protected>default>private)
Super关键字强行执行父类方法
继承: class 子类 extends 父类{}

package test;class Person{    private String name;    public void setName(String name) {         this.name = name;    }    public String getName() {        return name;    }       Person(int n){            //有参数的构造方法            System.out.println("Person() constructor is called !");          }}class Student extends Person{            //继承    private int score;    public int getScore() {        return score;    }    public void setScore(int score) {        this.score = score;    }    public void tell(){        System.out.println(getName() +": 得分"+getScore());    }    Student(){               //构造方法的继承        super(200);//构造方法先引用父类的构造方法,编译器找不到无参方法就报错.必须在子类构造方法最上面加一句super(int值)才可以通过编译.                                System.out.println("Student() constructor is called !");          }}public class zlk {  public static void main(String[] args) {    Student s= new Student();    s.setName("Zhang");    s.setScore(100);      s.tell();}  }

Java面向对象基本特征之多态

什么是多态
  面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
  多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
  实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
  多态的作用:消除类型之间的耦合关系。
  现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。

下面是多态存在的三个必要条件,要求大家做梦时都能背出来!
多态存在的三个必要条件!
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。

多态的好处:
1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。

package test;//父类 class Father{     //父类有一个打孩子方法     public void hitChild(){} } //子类1 class Son1 extends Father{     //重写父类打孩子方法     public void hitChild(){        System.out.println("为什么打我?我做错什么了!");     } } //子类2  class Son2 extends Father{     //重写父类打孩子方法     public void hitChild(){        System.out.println("我知道错了,别打了!");     } } //子类3 class Son3 extends Father{     //重写父类打孩子方法     public void hitChild(){        System.out.println("我跑,你打不着!");     } } //测试类 public class zlk{     public static void main(String args[]){        Father father;      father = new Son1();        father.hitChild();        father = new Son2();        father.hitChild();        father = new Son3();        father.hitChild();     } } 

Java面向对象-抽象类与接口

抽象类的特点:
1:包含一个抽象方法的类,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2:抽象方法只定义方法声明,并不定义方法实现。
3:抽象类不可以被创建对象(实例化)。
4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。子类必须重写抽象类中的所有抽象方法!

抽象类定义格式: abstract class className{属性;方法;抽象方法}

package test;abstract class Person{    private String name;    public void setName(String name) {         this.name = name;    }    public String getName() {        return name;    }    public abstract void tell();    public abstract void say();}class Student extends Person{                public void tell(){        System.out.println(getName());    }    public void say(){}; //子类必须重写抽象类中的所有抽象方法!}public class zlk {  public  static void main(String[] args) {    Student s= new Student();    s.setName("Zhang");      s.tell();}}

接 口:
1:是用关键字interface定义的特殊的类。里面全部由全局常量和公共的抽象方法组成。

interface Inter{    全局常量:public static final    抽象方法:public abstract}

2:接口中有抽象方法,说明接口不可以实例化。接口的子类必须实现了接口中所有的抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。子类必须重写抽象类中的所有抽象方法!
3:类与类之间存在着继承关系,类与接口中间存在的是实现关系。
    继承用extends ;实现用implements ;
4:接口和类不一样的地方,就是,接口可以被多实现,这就是多继承改良后的结果。java将多继承机制通过多实来体现。
5:一个类在继承另一个类的同时,还可以实现多个接口。所以接口的出现避免了单继承的局限性。还可以将类进行功能的扩展。

package test;interface Inter1{    public static final int num1=1;    public abstract void tell();}interface Inter2{    public static final int num2=2;    public abstract void say();}//一个接口通过extends关键字同时继承多个接口interface Inter3 extends Inter1,Inter2{    public static final int num3=3;    public abstract void call();}    abstract class Abs{        public abstract void print();    }//通过子类实现接口class A implements Inter1{    public void tell(){        System.out.println("A实现了接口"+num1);    }}//通过子类继承抽象类同时实现接口class B extends Abs implements Inter1,Inter3{    public void tell(){};    public void say(){};    public void call(){        System.out.println("INter3继承了接口"+num1+","+num2);    }    public void print(){        System.out.println("B继承抽象类Abs并实现了接口"+num1+","+num3);    }}public class zlk {  public  static void main(String[] args) {    A a=new A();     a.tell();     B b=new B();     b.call();     b.print();}}

Java面向对象-泛型

  泛型是Java SE1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

泛型类:

package test;public class zlk<T> {       //在类名后面添加了类型参数声明部分      private T t;      public void add(T t) {        this.t = t;      }       public T get() {        return t;      }      public static void main(String[] args) {         zlk<Integer> integerBox = new zlk<Integer>();//对象创建:在类名后面添加具体类型         zlk<String> stringBox = new zlk<String>();         integerBox.add(new Integer(10));         stringBox.add(new String("Hello World"));         System.out.printf("Integer Value :%d\n\n", integerBox.get());         System.out.printf("String Value :%s\n", stringBox.get());      }    }

泛型方法将数组排序输出:

package test;import java.util.Arrays;public class zlk{   // 泛型方法 printArray                            public static < E > void printArray( E[] inputArray )   {       //排序       Arrays.sort(inputArray);      // 输出数组元素                     for ( E element : inputArray ){                    System.out.printf( "%s ", element );         }         System.out.println();    }    public static void main( String args[] ) {        // 创建不同类型数组: Integer, Double 和 Character        Integer[] intArray = { 1, 5, 3, 2, 5 };        Double[] doubleArray = { 3.3, 2.2, 1.1, 4.4 };        Character[] charArray = { 'C', 'A', 'E', 'B', 'D' };        System.out.println( "Array integerArray contains:" );        printArray( intArray  ); // 传递一个整型数组        System.out.println( "\nArray doubleArray contains:" );        printArray( doubleArray ); // 传递一个双精度型数组        System.out.println( "\nArray characterArray contains:" );        printArray( charArray ); // 传递一个字符型型数组    } }

Java集合类详解

Collection集合类的基本结构:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map (key—-> value)
├Hashtable
├HashMap
└WeakHashMap

1、Collection接口
  Collection是最基本集合接口,它定义了一组允许重复的对象。Collection接口派生了两个子接口Set和List,分别定义了两种不同的存储方式。
2、 Set接口
  Set接口继承于Collection接口,它没有提供额外的方法, Set接口的集合类中的元素是不可重复的。但是可以排序。
  两个常用子类:
         1.散列存放:HashSet;
         2.有序存放:TreeSet;
3、 List接口
   List接口同样也继承于Collection接口,但是与Set接口恰恰相反,List接口的集合类中的元素是对象有序且可重复。
特征:有序且可重复。
  两个重要的实现类:ArrayList和LinkedList
  1.ArrayList特点是有序可重复的
  2.LinkedList是一个双向链表结构的。
4、Map接口
  Map也是接口,但没有继承Collection接口。该接口描述了从不重复的键到值的映射。Map接口用于维护键/值对(key/value pairs)。
  特征:它描述了从不重复的键到值的映射。
  两个重要的实现类:HashMap和TreeMap
  1.HashMap,中文叫散列表,基于哈希表实现,特点就是键值对的映射关系。一个key对应一个Value。HashMap中元素无序存放,Key不允许重复。更加适合于对元素进行插入、删除和定位。
  2.TreeMap,基于红黑书实现。TreeMap中的元素保持着某种固定的顺序。更加适合于对元素的顺序遍历。
5、Iterator接口
  Iterator接口,在C#里有例外一种说法IEnumerator,他们都是集合访问器,用于循环访问集合中的对象。所有实现了Collection接口的容器类都有iterator方法,用于返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,Iterator接口方法能以迭代方式逐个访问集合中各个元素,并可以从Collection中除去适当的元素。
6、Comparable接口
  Comparable可以用于比较的实现,实现了Comparable接口的类可以通过实现comparaTo方法从而确定该类对象的排序方式。

List接口,Iterator接口:

package test;  import java.util.ArrayList;  import java.util.Iterator;  import java.util.List;  public class zlk {     public static void main(String[] args) {         List<String> list = new ArrayList<String>();        //添加元素        list.add("aaa");        list.add("bbb");        list.add("ccc");        list.add("ddd");         list.add(null);         //遍历        for (String string : list) {            System.out.println(string);         }        System.out.println("---------------");        //修改        list.set(1, "bbb2");         //删除         list.remove("ccc");         //迭代器遍历         Iterator<String> iterator = list.iterator();        while(iterator.hasNext()){             System.out.println(iterator.next());        }         System.out.println("--------------");         list.clear(); //清空列表         System.out.println("清空后list的大小"+list.size());//打印大小        List<String> list2 = new ArrayList<String>();        list2.add("a");        list2.add("b");         //将list2添加到list中         list.addAll(list2);        //遍历        for (String string : list) {            System.out.println(string);        }     } }

HashMap接口,set,collection,Iterator接口:

package test;import java.util.*;public class  zlk {    public static void main(String[] args) {Map<String,String> map=new HashMap<String,String>();map.put("1","A");map.put("2.5","B");map.put("123L","C");String str=map.get("1");System.out.println(str);System.out.println(map.size());System.out.println(map.containsKey("2.5"));System.out.println(map.containsValue("D"));  //输出所有key Set<String> s=map.keySet(); Iterator<String> i=s.iterator(); while(i.hasNext()){     System.out.println(i.next()); } //输出所有value Collection<String> c=map.values(); Iterator<String> j=c.iterator(); while(j.hasNext()){     System.out.println(j.next()); }}}

Java本地文件操作

File类操作:

package test;import java.io.*;public class zlk {        public static void main(String[] args) {             File folder = new File("F:\\Hello");            folder.mkdirs();                  //创建文件夹               System.out.println("文件夹创建成功");          File folder1 = new File("F:\\World");            folder.renameTo(folder1);         //重命名              System.out.println("重命名成功");            folder.delete();             File file = new File("F:\\World\\d.txt");  //查找文件    if(file.exists()){    System.out.println(file.isFile());    System.out.println(file.isDirectory ());    }else{          System.out.println("文件不存在,马上进行创建!");          }            try {                file.createNewFile();        //创建文件            } catch (IOException e) {                e.printStackTrace();            }}}

Java中的IO操作

一:字节流
OutputStream和InputStream(基类)
FileOutputStream和FileInputStream(字节带缓冲输入、输出流)
BufferedInputStream和BufferedOutputStream(字节缓冲输入、输出流)

二:字符流
Reader和Writer(基类)
FileReader和FileWriter(定义字符输入、输出流)
BufferedReader和BufferedWriter(字符带缓冲输入、输出流)
LineNumberReader
IO操作:使用字节流读写数据

package test;import java.io.*;public class zlk {            public static void main(String[] args) {        try {  //创建两个文件夹        File file1 = new File("F:\\test\\input.txt" );            file1.createNewFile();               File file2 = new File("F:\\test\\output.txt" );            file2.createNewFile();      //输出流:向文件中写数据            FileOutputStream fos=new FileOutputStream("F:\\test\\input.txt");              String outString="HelloWorld";              byte output[]=outString.getBytes("UTF-8");              fos.write(output);      //输入流:从文件中读取数据                        FileInputStream fis = new FileInputStream("F:\\test\\input.txt");        byte input[]=new byte[20];        fis.read(input);        String s=new String(input,"UTF-8");        System.out.println(s);      //输出流:向另一文件中复制数据            FileOutputStream fos1=new FileOutputStream("F:\\test\\output.txt");                   fos1.write(s.getBytes());              fis.close();              fos.close();              fos1.close();            } catch (FileNotFoundException e) {                e.printStackTrace();            } catch (UnsupportedEncodingException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            }}}             

带有缓冲的字符流读写数据:

package test;import java.io.*;public class zlk {            public static void main(String[] args) {    BufferedReader br=new BufferedReader(new  InputStreamReader(System.in));//BufferedReader对象创建后获取控制台输入流File file=new File("F:\\test\\output.txt");   try {    FileWriter fw=new FileWriter(file);BufferedWriter bw=new BufferedWriter(fw); //加了一个缓冲,缓冲写满后再将数据写入硬盘 ,极大的提高了性能                 char[] cs=new char[50];                 br.read(cs);      //以使用read()方法从控制台读取一个字符                 String s=new String(cs);                 System.out.println(s.trim());                 bw.write(s); //将字符串写入磁盘文件中                 br.close();                bw.close();        } catch (IOException e) {            e.printStackTrace();        }     }}

Java多线程编程

  一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。

Java提供了两种创建线程方法:
• 通过继承Thread类本身: class NewThread extends Thread{}
  new NewThread().start();
• 通过实现Runable接口: class NewThread implements Runnable{}
  new Thread( new NewThread()).start();
  继承Thread类和实现Runnable接口实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务。如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
  实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制(继承了Thread类就不能再继承其他类了)
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

通过继承Thread类本身创建线程:

package test;class NewThread extends Thread {  //创建Thread的子类以控制线程的运行  public NewThread(String name){      super(name);               //调用父类构造方法给thread命名        }   public void run() {      try {         for(int i = 5; i > 0; i--) {            System.out.println("Thread " +getName()+":"+ i);                     Thread.sleep(50);        // 暂停线程,休眠         }     } catch (InterruptedException e) {         System.out.println("Child interrupted.");     }     System.out.println("Exiting child thread.");   }}public class zlk{   public static void main(String args[]) {      NewThread t1=new NewThread("A");      NewThread t2=new NewThread("B");      NewThread t3=new NewThread("C");      t1.start();      t2.start();      t3.start();      System.out.println(t1.isAlive());//判断线程是否启动   }}

通过实现Runnable接口创建线程:

package test;class NewThread implements Runnable {         String name;      public NewThread(String name){          this.name=name;                      }   public void run() {      try {         for(int i = 5; i > 0; i--) {            System.out.println("Thread " +name+":"+ i);                     Thread.sleep(50);        // 暂停线程         }     } catch (InterruptedException e) {         System.out.println("Child interrupted.");     }     System.out.println("Exiting child thread.");   }}public class zlk{     public static void main(String args[]) {          NewThread t1=new NewThread("A");         Thread demo=new Thread(t1);         demo.start();         for(int i=0;i<50;++i){             if(i>10){                 try{                     demo.join();     //强制执行demo                 }catch (Exception e) {                     e.printStackTrace();                 }             }             System.out.println("main 线程执行-->"+i);       }    }    }

线程同步:
  多线程环境中,可能存在多个线程同时使用某一资源造成资源冲突的情况(继承Thread类时)。多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。

例1:

package test;class MyThread extends Thread {  //创建Thread的子类以控制线程的运行  public MyThread(String name){     super(name);   }   public void run() {         while(true) {            sale();             }}   private static int tickets=5;    public static synchronized void sale()  { //这里就是对函数进行同步。     if(tickets>0)  {        try {           Thread.sleep(5000);       } catch (InterruptedException e) {           e.printStackTrace();       }   System.out.println(Thread.currentThread().getName()+" 剩余票数:"+ tickets);     }     tickets--;   }  }public class zlk {     public static void main(String[] args) {                       MyThread t1 = new MyThread("窗口A");             MyThread t2 = new MyThread("窗口B");             MyThread t3 = new MyThread("窗口C");             t1.start();             t2.start();             t3.start();             } }

例2:

package test;public class zlk implements Runnable{    private int tickets = 10;    public void run() {        int count = 0;        while(true) {            synchronized(this) {                if(tickets>-1) {                    try {                        Thread.sleep(500);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    count = 10 - tickets;                    System.out.println("当前有:"+tickets+" 张票"                            +" ,售出:"+count+"张票"                            +" ,售票员为:"+Thread.currentThread().getName());                    tickets--;                }else {                    break;               }            }        }    }public static void main(String[] args) {zlk r = new zlk();//调用Thread(Runnable threadOb,String threadName)构造方法.threadOb是一个实现Runnable 接口的类的实例,并且 threadName指定新线程的名字    Thread t1 = new Thread(r,"张三");    Thread t2 = new Thread(r,"李四");    Thread t3 = new Thread(r,"王五");    Thread t4 = new Thread(r,"赵六");    t1.start();    t2.start();    t3.start();    t4.start();    }}

Java中的Socket通信

Java socket通信已经被封装好了主要使用两个类ServerSocket 和Socket
首先写一个1v1的通信

Server:

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;  public class GreetingServer{       // 设置端口号       public static int portNo = 3333;       public static void main(String[] args) throws IOException {              ServerSocket s = new ServerSocket(portNo);              System.out.println("The Server is start: " + s);              // 阻塞,直到有客户端连接        Socket socket = s.accept();       try {                   System.out.println("Accept the Client: " + socket);                    //设置IO句柄 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);                             while (true)        {                    String str = in.readLine();                    if (str.equals("byebye"))        {                   break;            }            System.out.println("客户端发送的消息是: " + str);                            out.println("服务器收到:"+str);                     }              }         finally {                     System.out.println("close the Server socket and the io.");                     socket.close();                     s.close();              }    }}

Client:

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket; public class GreetingClient {       static String clientName = "Mike";       //端口号public static int portNo = 3333;       public static void main(String[] args) throws IOException{              // 设置连接地址类,连接本地              InetAddress addr = InetAddress.getByName("localhost");                      //要对应服务器端的3333端口号              Socket socket = new Socket(addr, portNo);              try{            System.out.println("socket = " + socket);                     // 设置IO句柄BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter out = new PrintWriter(new BufferedWriter(New OutputStreamWriter(socket.getOutputStream())), true);                     out.println("Hello Server,I am " + clientName);                     String str = in.readLine();                     System.out.println(str);                     out.println("byebye");              }finally {                     System.out.println("close the Client socket and the io.");                     socket.close();        }       }}

  通过程序里引入多线程的机制,可让一个服务器端同时监听并接收多个客户端的请求,并同步地为它们提供通讯服务。
  基于多线程的通讯方式,将大大地提高服务器端的利用效率,并能使服务器端能具备完善的服务功能。

Server:

package tcp;import java.io.*;import java.net.*;//第二步,由于我们在服务器端引入线程机制,所以我们要编写线程代码的主体执行类ServerThreadCode,这个类的代码如下所示:class ServerThreadCode extends Thread {       //客户端的socket       private Socket clientSocket;       //IO句柄       private BufferedReader sin;       private PrintWriter sout;           //默认的构造函数       public ServerThreadCode()       {}         public ServerThreadCode(Socket s) throws IOException        {              clientSocket = s;                          //初始化sin和sout的句柄              sin = new BufferedReader(new InputStreamReader(clientSocket                            .getInputStream()));        sout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(                            clientSocket.getOutputStream())), true);                           //开启线程              start();        }       //线程执行的主体函数       public void run()        {              try               {                     //用循环来监听通讯内容                     for(;;)                      {                String str = sin.readLine();                            //如果接收到的是byebye,退出本次通讯                            if (str.equals("byebye"))                            {                                        break;                            }                                 System.out.println("In Server reveived the info: " + str);                            sout.println(str);                     }                     System.out.println("closing the server socket!");              }         catch (IOException e)               {                     e.printStackTrace();              }               finally               {                     System.out.println("close the Server socket and the io.");                     try             {                            clientSocket.close();                     }                      catch (IOException e)                      {                            e.printStackTrace();                     }              }       }}public class ThreadServer {       //端口号       static final int portNo = 3333;       public static void main(String[] args) throws IOException        {              //服务器端的socket              ServerSocket s = new ServerSocket(portNo);              System.out.println("The Server is start: " + s);                    try               {                     for(;;)                                               {                  //阻塞,直到有客户端连接                            Socket socket = s.accept();                            //通过构造函数,启动线程                        new ServerThreadCode(socket);                     }              }           finally               {                     s.close();              }       }}

Client:

package tcp;import java.net.*;import java.io.*;//第二步,编写线程执行主体的ClientThreadCode类,同样,这个类通过继承Thread来实现线程的功能。class ClientThreadCode extends Thread {  //客户端的socket  private Socket socket;      //线程统计数,用来给线程编号  private static int cnt = 0;  private int clientId = cnt++;  private BufferedReader in;  private PrintWriter out;  //构造函数  public ClientThreadCode(InetAddress addr)   {    try     {      socket = new Socket(addr, 3333);    }    catch(IOException e)     {          e.printStackTrace();    }    //实例化IO对象try     {          in = new BufferedReader(             new InputStreamReader(socket.getInputStream()));           out = new PrintWriter(               new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);        //开启线程        start();     }      catch(IOException e)      {        //出现异常,关闭socket           try           {            socket.close();        }           catch(IOException e2)           {              e2.printStackTrace();                 }     }  }    //线程主体方法public void run()   {    try     {      out.println("Hello Server,My id is " + clientId );      String str = in.readLine();      System.out.println(str);      out.println("byebye");    }     catch(IOException e)     {       e.printStackTrace();      }    finally     {      try       {        socket.close();      }       catch(IOException e)       {              e.printStackTrace();      }        }  }}//第三步,编写客户端的主体代码,在这段代码里,将通过for循环,根据指定的待创建的线程数量,通过ClientThreadCode的构造函数,创建若干个客户端线程,同步地和服务器端通讯。public class ThreadClient {  public static void main(String[] args)       throws IOException, InterruptedException   {    int threadNo = 0;       InetAddress addr =        InetAddress.getByName("localhost");    for(threadNo = 0;threadNo<3;threadNo++)    {       new ClientThreadCode(addr);    }  }}
0 0