xml学习鉴定

实现招生录取系统中的部分功能(使用main方法作为程序入口)
1.	读XML文件,进过程序处理后,总成绩按降序排序,结果通过IO流输出到result_1.txt文件中。如:

班级[className classID]
学员姓名 学员ID[总分:457,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
学员姓名 学员ID[总分:453,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
学员姓名 学员ID[总分:448,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
班级[className classID]
学员姓名 学员ID[总分:457,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
学员姓名 学员ID[总分:454,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
学员姓名 学员ID[总分:445,学科ID:87,学科ID:83,学科ID:82,学科ID:83]

说明:
className classID用空格隔开,className为班级名称,classID为班级编号。
学员姓名 学员ID用空格隔开,每位学员成绩独占一行。总分为学员各学科成绩之和。


2.	通过IO读result_1.txt文件,以多线程方式实现大学录取学生功能
大学列表:清华大学、北京大学、南京大学、复旦大学、南京职业技术学院
说明:
A类大学为清华大学、北京大学,分数线为340,名额各为3名,;
B类大学为南京大学、复旦大学,分数线为320,名额各为10名;;
C类大学为南京职业技术学院,分数线为250,名额不限;
分数超过名额应该取最高分;达不到分数线可以不录取;
录取按大学类别进行:先A类,再B类,最后C类;
同类大学之间可以抢学生,同一学生只能被一所大学录取,以先录取为准;
结果通过IO输出result_2.txt,如:

清华大学:
学员姓名 学员ID[总分:457,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
北京大学:学员姓名 学员ID[总分:448,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
南京大学:学员姓名 学员ID[总分:448,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
复旦大学:学员姓名 学员ID[总分:448,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
南京职业技术学院:学员姓名 学员ID[总分:448,学科ID:87,学科ID:83,学科ID:82,学科ID:83]
未被录取学员:
学员姓名 学员ID[总分:128],学员姓名 学员ID[总分:215]


xml文档如下:
<root>
<!--表结构-->
<tables>
  <!--学员表-->
<table id="1000" name="studentTbl">
      <fields>
        <field id="studentId" /><!--学号-->
        <field id="name" /><!--姓名-->
        <field id="sex "/><!--性别-->
      </fields>
</table>

  <!--班级表-->
<table id="1001" name="classTbl">
      <fields>
        <field id="classId" /><!--班级编号-->
        <field id="name" /><!--班级名称-->
      </fields>
</table>

  <!--班级学员表-->
<table id="1004" name="classStudentTbl">
      <fields>
        <field id="classId" /><!--班级编号-->
        <field id="studentId" /><!--学号-->
      </fields>
</table>	

  <!--学科表-->
<table id="1002" name="subjectTbl">
      <fields>
        <field id="subjectId" /><!--学科编号-->
        <field id="name" /><!--学科名称-->
      </fields>
</table>

  <!--成绩表-->
<table id="1003" name="scoreTbl">
      <fields>
        <field id="studentId" /><!--学号-->
        <field id="subjectId" /><!--学科编号-->
        <field id="score" /><!--成绩-->
      </fields>
</table>	

</tables>

<!--数据信息,字段值以','分隔-->
<datas>

  <!--学员数据-->
<data tableid="1000">
<fields-data>st001,张一,男</fields-data>
<fields-data>st002,李二,男</fields-data>
<fields-data>st003,王三,女</fields-data>
<fields-data>st004,杨四,男</fields-data>
<fields-data>st005,赵五,男</fields-data>
<fields-data>st006,郑陆,女</fields-data>
<fields-data>st007,林世,男</fields-data>
<fields-data>st008,胡长,男</fields-data>
<fields-data>st009,邹家,男</fields-data>
<fields-data>st010,李方,男</fields-data>
<fields-data>st011,宁可,男</fields-data>
<fields-data>st012,张杂,男</fields-data>
<fields-data>st013,李度,男</fields-data>
<fields-data>st014,王等,女</fields-data>
<fields-data>st015,杨角,男</fields-data>
<fields-data>st016,赵度,男</fields-data>
<fields-data>st017,郑来,男</fields-data>
<fields-data>st018,林衡,男</fields-data>
<fields-data>st019,胡量,男</fields-data>
<fields-data>st020,邹代,女</fields-data>
<fields-data>st021,李码,男</fields-data>
<fields-data>st022,宁的,男</fields-data>
<fields-data>st023,张质,男</fields-data>
</data>

  <!--班级数据-->
<data tableid="1001">
<fields-data>1,一年级</fields-data>
<fields-data>2,二年级</fields-data>
<fields-data>3,三年级</fields-data>
</data>

  <!--学员班级信息-->
<data tableid="1004">
<fields-data>1,st001</fields-data>
<fields-data>2,st002</fields-data>
<fields-data>3,st003</fields-data>
<fields-data>1,st004</fields-data>
<fields-data>2,st005</fields-data>
<fields-data>3,st006</fields-data>
<fields-data>1,st007</fields-data>
<fields-data>2,st008</fields-data>
<fields-data>3,st009</fields-data>
<fields-data>2,st010</fields-data>
<fields-data>3,st011</fields-data>
<fields-data>3,st012</fields-data>
<fields-data>1,st013</fields-data>
<fields-data>1,st014</fields-data>
<fields-data>2,st015</fields-data>
<fields-data>3,st016</fields-data>
<fields-data>3,st017</fields-data>
<fields-data>2,st018</fields-data>
<fields-data>1,st019</fields-data>
<fields-data>1,st020</fields-data>
<fields-data>2,st021</fields-data>
<fields-data>3,st022</fields-data>
<fields-data>2,st023</fields-data>
<fields-data>3,st024</fields-data>
</data>

<!--学科数据-->
<data tableid="1002">
<fields-data>1,英语</fields-data>
<fields-data>2,化学</fields-data>
<fields-data>3,代数</fields-data>
<fields-data>4,计算机</fields-data>
</data>
<!--成绩数据-->
<data tableid="1003">
<fields-data>st001,1,80</fields-data>
<fields-data>st001,2,90</fields-data>
<fields-data>st001,3,70</fields-data>
<fields-data>st001,4,100</fields-data>
<fields-data>st002,1,77</fields-data>
<fields-data>st002,2,88</fields-data>
<fields-data>st002,3,99</fields-data>
<fields-data>st002,4,56</fields-data>
<fields-data>st003,1,96</fields-data>
<fields-data>st003,2,56</fields-data>
<fields-data>st003,3,88</fields-data>
<fields-data>st003,4,69</fields-data>
<fields-data>st004,1,78</fields-data>
<fields-data>st004,2,85</fields-data>
<fields-data>st004,3,83</fields-data>
<fields-data>st004,4,96</fields-data>
<fields-data>st005,1,79</fields-data>
<fields-data>st005,2,87</fields-data>
<fields-data>st005,3,91</fields-data>
<fields-data>st005,4,85</fields-data>
<fields-data>st006,1,79</fields-data>
<fields-data>st006,2,87</fields-data>
<fields-data>st006,3,68</fields-data>
<fields-data>st006,4,86</fields-data>
<fields-data>st007,1,55</fields-data>
<fields-data>st007,2,78</fields-data>
<fields-data>st007,3,90</fields-data>
<fields-data>st007,4,68</fields-data>
<fields-data>st008,1,69</fields-data>
<fields-data>st008,2,86</fields-data>
<fields-data>st008,3,75</fields-data>
<fields-data>st008,4,69</fields-data>
<fields-data>st009,1,84</fields-data>
<fields-data>st009,2,69</fields-data>
<fields-data>st009,3,90</fields-data>
<fields-data>st009,4,49</fields-data>
<fields-data>st010,1,77</fields-data>
<fields-data>st010,2,86</fields-data>
<fields-data>st010,3,99</fields-data>
<fields-data>st010,4,82</fields-data>
<fields-data>st011,1,67</fields-data>
<fields-data>st011,2,87</fields-data>
<fields-data>st011,3,69</fields-data>
<fields-data>st011,4,56</fields-data>
<fields-data>st012,1,44</fields-data>
<fields-data>st012,2,66</fields-data>
<fields-data>st012,3,99</fields-data>
<fields-data>st012,4,89</fields-data>
<fields-data>st013,1,67</fields-data>
<fields-data>st013,2,87</fields-data>
<fields-data>st013,3,78</fields-data>
<fields-data>st013,4,78</fields-data>
<fields-data>st014,1,56</fields-data>
<fields-data>st014,2,78</fields-data>
<fields-data>st014,3,88</fields-data>
<fields-data>st014,4,11</fields-data>
<fields-data>st015,1,0</fields-data>
<fields-data>st015,2,44</fields-data>
<fields-data>st015,3,66</fields-data>
<fields-data>st015,4,99</fields-data>
<fields-data>st016,1,67</fields-data>
<fields-data>st016,2,98</fields-data>
<fields-data>st016,3,78</fields-data>
<fields-data>st016,4,99</fields-data>
<fields-data>st017,1,89</fields-data>
<fields-data>st017,2,88</fields-data>
<fields-data>st017,3,90</fields-data>
<fields-data>st017,4,96</fields-data>
<fields-data>st018,1,93</fields-data>
<fields-data>st018,2,95</fields-data>
<fields-data>st018,3,96</fields-data>
<fields-data>st018,4,91</fields-data>
<fields-data>st019,1,98</fields-data>
<fields-data>st019,2,94</fields-data>
<fields-data>st019,3,93</fields-data>
<fields-data>st019,4,89</fields-data>	
<fields-data>st020,1,87</fields-data>
<fields-data>st020,2,96</fields-data>
<fields-data>st020,3,79</fields-data>
<fields-data>st020,4,82</fields-data>
<fields-data>st021,1,77</fields-data>
<fields-data>st021,2,87</fields-data>
<fields-data>st021,3,89</fields-data>
<fields-data>st021,4,86</fields-data>
<fields-data>st022,1,94</fields-data>
<fields-data>st022,2,76</fields-data>
<fields-data>st022,3,69</fields-data>
<fields-data>st022,4,79</fields-data>
<fields-data>st023,1,87</fields-data>
<fields-data>st023,2,57</fields-data>
<fields-data>st023,3,48</fields-data>
<fields-data>st023,4,48</fields-data>
<fields-data>st024,1,56</fields-data>
<fields-data>st024,2,68</fields-data>
<fields-data>st024,3,78</fields-data>
<fields-data>st024,4,81</fields-data>
<fields-data>st025,1,99</fields-data>
<fields-data>st025,2,47</fields-data>
<fields-data>st025,3,68</fields-data>
<fields-data>st025,4,98</fields-data>
<fields-data>st026,1,69</fields-data>
<fields-data>st026,2,95</fields-data>
<fields-data>st026,3,75</fields-data>
<fields-data>st026,4,95</fields-data>
<fields-data>st027,1,84</fields-data>
<fields-data>st027,2,85</fields-data>
<fields-data>st027,3,96</fields-data>
<fields-data>st027,4,76</fields-data>
<fields-data>st028,1,83</fields-data>
<fields-data>st028,2,95</fields-data>	
</data>

</datas>
</root>



实现:
import java.util.Set;
import java.util.TreeSet;

/**
 * 班级类
 */

public class Class implements Comparable<Class>
{
    private int classId;
    private String name;
    //维护本班级下面所有的student
    private Set<Student> students;

    public Class()
    {
        //有序存储student对象
        students = new TreeSet<Student>();
    }

    public Class(int classId, String name)
    {
        this();
        this.classId = classId;
        this.name = name;
    }

    public void setStudents(Set<Student> students)
    {
        this.students = students;
    }

    public Set<Student> getStudents()
    {
        return students;
    }

    public int getClassId()
    {
        return classId;
    }

    public void setClassId(int classId)
    {
        this.classId = classId;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    @Override
    public String toString()
    {
        return "班级[" + name + " " + classId + "]";
    }

    @Override
    public int compareTo(Class o)
    {
        return classId - o.classId;
    }
}


import java.util.Set;
import java.util.TreeSet;

/**
 * 学生类
 */

public class Student implements Comparable<Student>
{
    private String studentId;
    private String name;
    private String sex;
    private Set<Score> scores;

    public Student()
    {
        scores = new TreeSet<Score>();
    }

    public Student(String studentId, String name, String sex)
    {
        this();
        this.studentId = studentId;
        this.name = name;
        this.sex = sex;
    }

    public Set<Score> getScores()
    {
        return scores;
    }

    public void setScores(Set<Score> scores)
    {
        this.scores = scores;
    }

    public String getStudentId()
    {
        return studentId;
    }

    public void setStudentId(String studentId)
    {
        this.studentId = studentId;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getSex()
    {
        return sex;
    }

    public void setSex(String sex)
    {
        this.sex = sex;
    }

    //按总成绩对学生排序,如果总成绩相同,按学号排序
    @Override
    public int compareTo(Student o)
    {
        float total = 0f;
        for (Score score : scores)
            total += score.getScore();

        float o_total = 0f;
        for (Score score : o.getScores())
            o_total += score.getScore();
        int result = (int) (o_total - total);
        if (result != 0)
            return result;
        return studentId.compareTo(o.studentId);
    }

    @Override
    public String toString()
    {
        StringBuilder result = new StringBuilder();
        result.append(name).append(' ').append(studentId).append("[总分:%3d, ");
        float total = 0f;
        for (Score score : scores)
        {
            result.append(score.getCourse().getName()).append(":").append(String.format("%3d", (int) score.getScore()))
                    .append(", ");
            total += score.getScore();
        }
        return String.format(result.substring(0, result.length() - 2) + "]", (int) total);
    }
}


/**
 * 成绩类
 */

public class Score implements Comparable<Score>
{
    private float score;
    private Student student;
    private Course course;

    public Score(float score, Student student, Course course)
    {
        this.score = score;
        this.student = student;
        this.course = course;
    }

    public Score()
    {
    }

    public float getScore()
    {
        return score;
    }

    public void setScore(float score)
    {
        this.score = score;
    }

    public Student getStudent()
    {
        return student;
    }

    public void setStudent(Student student)
    {
        this.student = student;
    }

    public Course getCourse()
    {
        return course;
    }

    public void setCourse(Course course)
    {
        this.course = course;
    }

    //按课程号进行排序
    @Override
    public int compareTo(Score o)
    {
        return course.getSujectId() - o.course.getSujectId();
    }
}


/**
 * 课程类
 */

public class Course
{
    private int sujectId;
    private String name;

    public Course()
    {
    }

    public Course(int sujectId, String name)
    {
        this.sujectId = sujectId;
        this.name = name;
    }

    public int getSujectId()
    {
        return sujectId;
    }

    public void setSujectId(int sujectId)
    {
        this.sujectId = sujectId;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

}


import java.io.IOException;
import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 *  解析xml文档的工具类 
 */

public class DataParser
{
    //定义解析数据过程中需要用到的一些常量数据
    private static final String DATA_ELEMENT = "data";
    private static final String FIELD_DATA_ELEMENT = "fields-data";
    private static final String TABLE_ID_ATTRIBUTE = "tableid";
    private static final String STUDENT_DATA = "1000";
    private static final String CLASS_DATA = "1001";
    private static final String COURSE_DATA = "1002";
    private static final String SCORE_DATA = "1003";
    private static final String STUDENT_CLASS_DATA = "1004";

    public static void main(String[] args)
    {
        Set<Class> classes = getClasses("src/data.xml");
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream("result_1.txt"), "UTF-8"), true);
        for (Class cls : classes)
        {
            writer.println(cls);
            for (Student student : cls.getStudents())
            {
                writer.println(student);
            }
        }
        writer.close();
    }

    public static Set<Class> getClasses(String filePath)
    {
        DocumentBuilderFactory parserFactory = DocumentBuilderFactory.newInstance();
        //解析完成的数据 暂时存储在map集合中 方便查找
        HashMap<Integer, Class> cls_map = new HashMap<Integer, Class>();
        HashMap<String, Student> stu_map = new HashMap<String, Student>();
        HashMap<Integer, Course> cour_map = new HashMap<Integer, Course>();

        try
        {
            DocumentBuilder parser = parserFactory.newDocumentBuilder();
            Document doc = parser.parse(filePath);
            XPath xpath = XPathFactory.newInstance().newXPath();
            //xpath表达式 %s表示待替换的属性值
            String expr = "//" + DATA_ELEMENT + "[@" + TABLE_ID_ATTRIBUTE + "=%s]";
            
            //解析class数据
            Element cls_elt = (Element) xpath.compile(String.format(expr, CLASS_DATA)).evaluate(doc, XPathConstants.NODE);
            NodeList cls_items = cls_elt.getElementsByTagName(FIELD_DATA_ELEMENT);
            for (int i = 0; i < cls_items.getLength(); i++)
            {
                String item = cls_items.item(i).getTextContent();
                String[] parts = item.split(",");
                if (parts.length != 2)
                    throw new IllegalArgumentException("invalid class data item: " + item);

                int classId = Integer.parseInt(parts[0].trim());
                String name = parts[1].trim();
                cls_map.put(classId, new Class(classId, name));
            }

            //解析student数据
            Element stu_elt = (Element) xpath.compile(String.format(expr, STUDENT_DATA)).evaluate(doc, XPathConstants.NODE);
            NodeList stu_items = stu_elt.getElementsByTagName(FIELD_DATA_ELEMENT);
            for (int i = 0; i < stu_items.getLength(); i++)
            {
                String item = stu_items.item(i).getTextContent();
                String[] parts = item.split(",");
                if (parts.length != 3)
                    throw new IllegalArgumentException("invalid student data item: " + item);

                String studentId = parts[0].trim();
                String name = parts[1].trim();
                String sex = parts[2].trim();
                stu_map.put(studentId, new Student(studentId, name, sex));
            }

            //解析course数据
            Element cour_elt = (Element) xpath.compile(String.format(expr, COURSE_DATA)).evaluate(doc, XPathConstants.NODE);
            NodeList cour_items = cour_elt.getElementsByTagName(FIELD_DATA_ELEMENT);
            for (int i = 0; i < cour_items.getLength(); i++)
            {
                String item = cour_items.item(i).getTextContent();
                String[] parts = item.split(",");
                if (parts.length != 2)
                    throw new IllegalArgumentException("invalid course data item: " + item);

                int courseId = Integer.parseInt(parts[0].trim());
                String name = parts[1].trim();
                cour_map.put(courseId, new Course(courseId, name));
            }

            //解析score数据
            Element score_elt = (Element) xpath.compile(String.format(expr, SCORE_DATA)).evaluate(doc, XPathConstants.NODE);
            NodeList score_items = score_elt.getElementsByTagName(FIELD_DATA_ELEMENT);
            Score score;
            for (int i = 0; i < score_items.getLength(); i++)
            {
                String item = score_items.item(i).getTextContent();
                String[] parts = item.split(",");
                if (parts.length != 3)
                    throw new IllegalArgumentException("invalid score data item: " + item);

                String studentId = parts[0].trim();
                Student stu = stu_map.get(studentId);
                if (stu == null)
                {
                    System.out.println("invalid student id: " + studentId);
                    continue;
                }

                int courseId = Integer.parseInt(parts[1].trim());
                Course cour = cour_map.get(courseId);
                if (cour == null)
                {
                    System.out.println("invalid course id: " + courseId);
                    continue;
                }

                float grade = Float.parseFloat(parts[2].trim());
                score = new Score();
                score.setScore(grade);
                score.setCourse(cour);
                score.setStudent(stu);

                stu.getScores().add(score);
            }

            //解析class-student数据
            Element stu_cls_elt = (Element) xpath.compile(String.format(expr, STUDENT_CLASS_DATA)).evaluate(doc,
                    XPathConstants.NODE);
            NodeList stu_cls_items = stu_cls_elt.getElementsByTagName(FIELD_DATA_ELEMENT);
            for (int i = 0; i < stu_cls_items.getLength(); i++)
            {
                String item = stu_cls_items.item(i).getTextContent();
                String[] parts = item.split(",");
                if (parts.length != 2)
                    throw new IllegalArgumentException("invalid class to student mapping data item: " + item);

                int classId = Integer.parseInt(parts[0].trim());
                String studentId = parts[1].trim();
                Class cls = cls_map.get(classId);
                if (cls == null)
                {
                    System.out.println("invalid class id: " + classId);
                    continue;
                }

                Student stu = stu_map.get(studentId);
                if (stu == null)
                {
                    System.out.println("invalid student id: " + studentId);
                    continue;
                }
                cls.getStudents().add(stu);
            }
        }
        catch (ParserConfigurationException e)
        {
            throw new RuntimeException("parser configuration error", e);
        }
        catch (SAXException e)
        {
            throw new RuntimeException("parse error", e);
        }
        catch (IOException e)
        {
            throw new RuntimeException("io operation error", e);
        }
        catch (XPathExpressionException e)
        {
            throw new RuntimeException("xpath expression error", e);
        }
        
        //最终将class数据存储到treemap集合返回
        return new TreeSet<Class>(cls_map.values());
    }
}


-------------------执行结果 result_1.txt-------------------------
班级[一年级 1]
胡量 st019[总分:374, 英语: 98, 化学: 94, 代数: 93, 计算机: 89]
邹代 st020[总分:344, 英语: 87, 化学: 96, 代数: 79, 计算机: 82]
杨四 st004[总分:342, 英语: 78, 化学: 85, 代数: 83, 计算机: 96]
张一 st001[总分:340, 英语: 80, 化学: 90, 代数: 70, 计算机:100]
李度 st013[总分:310, 英语: 67, 化学: 87, 代数: 78, 计算机: 78]
林世 st007[总分:291, 英语: 55, 化学: 78, 代数: 90, 计算机: 68]
王等 st014[总分:233, 英语: 56, 化学: 78, 代数: 88, 计算机: 11]
班级[二年级 2]
林衡 st018[总分:375, 英语: 93, 化学: 95, 代数: 96, 计算机: 91]
李方 st010[总分:344, 英语: 77, 化学: 86, 代数: 99, 计算机: 82]
赵五 st005[总分:342, 英语: 79, 化学: 87, 代数: 91, 计算机: 85]
李码 st021[总分:339, 英语: 77, 化学: 87, 代数: 89, 计算机: 86]
李二 st002[总分:320, 英语: 77, 化学: 88, 代数: 99, 计算机: 56]
胡长 st008[总分:299, 英语: 69, 化学: 86, 代数: 75, 计算机: 69]
张质 st023[总分:240, 英语: 87, 化学: 57, 代数: 48, 计算机: 48]
杨角 st015[总分:209, 英语:  0, 化学: 44, 代数: 66, 计算机: 99]
班级[三年级 3]
郑来 st017[总分:363, 英语: 89, 化学: 88, 代数: 90, 计算机: 96]
赵度 st016[总分:342, 英语: 67, 化学: 98, 代数: 78, 计算机: 99]
郑陆 st006[总分:320, 英语: 79, 化学: 87, 代数: 68, 计算机: 86]
宁的 st022[总分:318, 英语: 94, 化学: 76, 代数: 69, 计算机: 79]
王三 st003[总分:309, 英语: 96, 化学: 56, 代数: 88, 计算机: 69]
张杂 st012[总分:298, 英语: 44, 化学: 66, 代数: 99, 计算机: 89]
邹家 st009[总分:292, 英语: 84, 化学: 69, 代数: 90, 计算机: 49]
宁可 st011[总分:279, 英语: 67, 化学: 87, 代数: 69, 计算机: 56]



public class SelectStudent
{
    //构建一个简单的Student类,存储从txt文件解析出来的Student对象
    static class SimpleStudent implements Comparable<SimpleStudent>
    {
        //总成绩
        private int score;
        //考生详细信息
        private String info;

        public SimpleStudent()
        {
        }

        public SimpleStudent(int score, String info)
        {
            this.score = score;
            this.info = info;
        }

        public int getScore()
        {
            return score;
        }

        public void setScore(int score)
        {
            this.score = score;
        }

        public String getInfo()
        {
            return info;
        }

        public void setInfo(String info)
        {
            this.info = info;
        }

        //按总成绩排序,如果总成绩相同,按详细信息排序
        @Override
        public int compareTo(SimpleStudent o)
        {
            int result = o.score - score;
            if (result != 0)
                return result;
            return info.compareTo(o.info);
        }

        @Override
        public String toString()
        {
            return info;
        }
    }

    private final Lock lock = new ReentrantLock();
    //A类线程等待的信号
    private final Condition con_a = lock.newCondition();
    //B类线程等待的信号
    private final Condition con_b = lock.newCondition();
    //C类线程等待的信号    
    private final Condition con_c = lock.newCondition();
    //使用一个线程池运行相关的Task
    private ExecutorService executor = Executors.newCachedThreadPool();
    private int state = 0;

    public SelectStudent()
    {
    }

    public void shutdownExecutorNow()
    {
        if (!executor.isShutdown())
            executor.shutdownNow();
    }

    //线程管理类
    abstract class Monitor implements Runnable
    {
        CountDownLatch cdl_before;
        CountDownLatch cdl_after;

        Monitor(CountDownLatch cdl_before, CountDownLatch cdl_after)
        {
            this.cdl_before = cdl_before;
            this.cdl_after = cdl_after;
        }

        @Override
        public void run()
        {
            //获得锁
            lock.lock();
            try
            {
                //具体实现由子类完成
                process();
            }
            catch (InterruptedException e)
            {
                throw new RuntimeException("interrupted error", e);
            }
            finally
            {
                //释放锁
                lock.unlock();
            }
        }

        abstract void process() throws InterruptedException;
    }

    //A类管理线程
    class MonitorA extends Monitor
    {
        MonitorA(CountDownLatch cdl_before, CountDownLatch cdl_after)
        {
            super(cdl_before, cdl_after);
        }

        @Override
        void process() throws InterruptedException
        {
            //当state=0 表明当前状态允许执行
            while (state % 3 != 0)
                //若条件不符合,在con_a条件上等待
                con_a.await();

            //通知A类线程开始执行
            cdl_before.countDown();
            //等待所有A类线程执行完成
            cdl_after.await();
            state++;
            //通知B类管理线程开始执行
            con_b.signal();
        }
    }

    //B类管理线程
    class MonitorB extends Monitor
    {
        MonitorB(CountDownLatch cdl_before, CountDownLatch cdl_after)
        {
            super(cdl_before, cdl_after);
        }

        @Override
        void process() throws InterruptedException
        {
            //state=1 允许执行
            while (state % 3 != 1)
                //若条件不符合,在con_b条件上等待
                con_b.await();

            //通知B类线程开始执行
            cdl_before.countDown();
            //等待所有B类线程执行完成
            cdl_after.await();
            state++;
            //通知C类管理线程开始执行
            con_c.signal();
        }
    }

    //C类管理线程
    class MonitorC extends Monitor
    {
        MonitorC(CountDownLatch cdl_before, CountDownLatch cdl_after)
        {
            super(cdl_before, cdl_after);
        }

        @Override
        void process() throws InterruptedException
        {
            //state=2 运行执行
            while (state % 3 != 2)
                //若条件不符合,在con_c条件上等待
                con_c.await();

            //通知所有C类线程执行
            cdl_before.countDown();
        }
    }

    //模拟TimeUnit.unit.sleep 非阻塞方法
    void sleep(TimeUnit unit, long duration)
    {
        long startTime = System.nanoTime();
        while (System.nanoTime() - startTime < unit.toNanos(duration))
        {
        }
    }

    //录取考生线程(A类,B类,C类)
    class SelectTask implements Runnable
    {
        //学校名称
        private String name;
        //录取人数
        private int num;
        //分数线
        private int grade;
        //考生列表
        private List<SimpleStudent> students;
        //消息队列
        private ConcurrentLinkedQueue<String> queue;
        //任务开始条件
        private CountDownLatch cdl_before;
        //任务结束条件
        private CountDownLatch cdl_after;

        SelectTask(String schoolName, List<SimpleStudent> stus, ConcurrentLinkedQueue<String> queue, int selectNum, int grade,
                CountDownLatch cdl_before, CountDownLatch cdl_after)
        {
            name = schoolName;
            students = stus;
            num = selectNum;
            this.grade = grade;
            this.queue = queue;
            this.cdl_before = cdl_before;
            this.cdl_after = cdl_after;
        }

        @Override
        public void run()
        {
            try
            {
                //等待任务开始条件
                cdl_before.await();
                SimpleStudent student;
                int i = 0;
                try
                {
                    //开始录取操作
                    for (i = 0; i < num; i++)
                    {
                        sleep(TimeUnit.MILLISECONDS, 5);
                        synchronized (students)
                        {
                            //如果学校列表已经为空,强制终止整个录取过程(强制关闭线程池)
                            if (students.isEmpty())
                            {
                                queue.offer(name + ": 没有可录取的学生!");
                                shutdownExecutorNow();
                                return;
                            }

                            student = students.get(0);
                            //如果没有达到分数线,终止录取过程
                            if (student.getScore() < grade)
                                break;
                            
                            //将录取信息加入到消息队列
                            queue.offer(name + ": " + students.remove(0).info);
                        }
                    }
                }
                finally
                {
                    //将统计消息加入消息队列
                    //放在finally中,即使强制终止当前线程,也会执行该语句
                    queue.offer(name + ":[" + ((num == i || num == Integer.MAX_VALUE) ? "达标" : "未达标") + "] 当前录取" + i + "/总名额"
                            + (num == Integer.MAX_VALUE ? "(无限制)" : num));
                }
            }
            catch (InterruptedException e)
            {
                throw new RuntimeException("interrupted error", e);
            }
            finally
            {
                //当前任务运行结束
                cdl_after.countDown();
            }
        }
    }

    //打印未被录取考生信息的线程
    class NotSelectTask implements Runnable
    {
        //考生列表
        private List<SimpleStudent> students;
        //消息队列
        private ConcurrentLinkedQueue<String> queue;
        //任务开始条件
        private CountDownLatch cdl;

        public NotSelectTask(List<SimpleStudent> students, ConcurrentLinkedQueue<String> queue, CountDownLatch cdl)
        {
            this.students = students;
            this.queue = queue;
            this.cdl = cdl;
        }

        @Override
        public void run()
        {
            try
            {
                //等待任务开始条件(所有C类线程执行完毕)
                cdl.await();
                while (!students.isEmpty())
                    //将未被录取考生信息加入消息队列
                    queue.offer("未被录取:" + students.remove(0).info);

                //终止线程池
                executor.shutdown();
            }
            catch (InterruptedException e)
            {
                throw new RuntimeException("wait interrupted", e);
            }
        }
    }

    //消息处理线程 从消息队列取出消息,通过输出流写到文件中
    class OutputTask implements Runnable
    {
        private ConcurrentLinkedQueue<String> queue;
        private PrintWriter writer;

        OutputTask(ConcurrentLinkedQueue<String> queue, String outFile)
        {
            this.queue = queue;
            try
            {
                writer = new PrintWriter(new FileOutputStream(outFile));
            }
            catch (FileNotFoundException e)
            {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void run()
        {
            String content = null;
            while (true)
            {
                //如果录取线程池已经终止且当前消息队列为空,退出
                if (executor.isTerminated() && queue.isEmpty())
                    break;
                content = queue.poll();
                if (content != null)
                    writer.println(content);
                writer.flush();
            }
            writer.close();
        }
    }

    public static void main(String[] args) throws Exception
    {
        SelectStudent ss = new SelectStudent();
        List<SimpleStudent> stus = ss.parseTextFile("result_1.txt");
        ss.select(stus);
    }

    public void select(List<SimpleStudent> list)
    {
        //消息队列
        ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();
        //构建消息处理线程
        new Thread(new OutputTask(queue, "result_2.txt")).start();

        CountDownLatch cdl_11 = new CountDownLatch(1);
        CountDownLatch cdl_21 = new CountDownLatch(2);
        //A类管理线程
        executor.execute(new MonitorA(cdl_11, cdl_21));
        //A类线程
        executor.execute(new SelectTask("清华大学", list, queue, 3, 340, cdl_11, cdl_21));
        //A类线程
        executor.execute(new SelectTask("北京大学", list, queue, 3, 340, cdl_11, cdl_21));

        CountDownLatch cdl_12 = new CountDownLatch(1);
        CountDownLatch cdl_22 = new CountDownLatch(2);
        //B类管理线程
        executor.execute(new MonitorB(cdl_12, cdl_22));
        //B类线程
        executor.execute(new SelectTask("南京大学", list, queue, 10, 320, cdl_12, cdl_22));
        //B类线程
        executor.execute(new SelectTask("复旦大学", list, queue, 10, 320, cdl_12, cdl_22));

        CountDownLatch cdl_13 = new CountDownLatch(1);
        CountDownLatch cdl_23 = new CountDownLatch(1);
        //C类管理线程
        executor.execute(new MonitorC(cdl_13, cdl_23));
        //C类线程
        executor.execute(new SelectTask("南京职业技术学院", list, queue, Integer.MAX_VALUE, 250, cdl_13, cdl_23));

        //处理未被录取考生线程
        executor.execute(new NotSelectTask(list, queue, cdl_23));
    }

    //从txt文档解析考生信息,并按总成绩进行排序
    public List<SimpleStudent> parseTextFile(String filename) throws Exception
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"));
        String line = null;
        List<SimpleStudent> students = new ArrayList<SimpleStudent>();
        SimpleStudent stu;
        while (null != (line = reader.readLine()))
        {
            int index = line.indexOf("总分");
            if (index == -1)
                continue;

            String score_str = line.substring(index + 3, line.indexOf(",", index));
            stu = new SimpleStudent(Integer.parseInt(score_str), line);
            students.add(stu);
        }
        Collections.sort(students);
        return students;
    }
}


-------------------执行结果 result_2.txt-------------------------
北京大学: 林衡 st018[总分:375, 英语: 93, 化学: 95, 代数: 96, 计算机: 91]
北京大学: 胡量 st019[总分:374, 英语: 98, 化学: 94, 代数: 93, 计算机: 89]
清华大学: 郑来 st017[总分:363, 英语: 89, 化学: 88, 代数: 90, 计算机: 96]
北京大学: 李方 st010[总分:344, 英语: 77, 化学: 86, 代数: 99, 计算机: 82]
北京大学:[达标] 当前录取3/总名额3
清华大学: 邹代 st020[总分:344, 英语: 87, 化学: 96, 代数: 79, 计算机: 82]
清华大学: 杨四 st004[总分:342, 英语: 78, 化学: 85, 代数: 83, 计算机: 96]
清华大学:[达标] 当前录取3/总名额3
复旦大学: 赵五 st005[总分:342, 英语: 79, 化学: 87, 代数: 91, 计算机: 85]
复旦大学: 赵度 st016[总分:342, 英语: 67, 化学: 98, 代数: 78, 计算机: 99]
复旦大学: 张一 st001[总分:340, 英语: 80, 化学: 90, 代数: 70, 计算机:100]
复旦大学: 李码 st021[总分:339, 英语: 77, 化学: 87, 代数: 89, 计算机: 86]
南京大学: 李二 st002[总分:320, 英语: 77, 化学: 88, 代数: 99, 计算机: 56]
复旦大学: 郑陆 st006[总分:320, 英语: 79, 化学: 87, 代数: 68, 计算机: 86]
南京大学:[未达标] 当前录取1/总名额10
复旦大学:[未达标] 当前录取5/总名额10
南京职业技术学院: 宁的 st022[总分:318, 英语: 94, 化学: 76, 代数: 69, 计算机: 79]
南京职业技术学院: 李度 st013[总分:310, 英语: 67, 化学: 87, 代数: 78, 计算机: 78]
南京职业技术学院: 王三 st003[总分:309, 英语: 96, 化学: 56, 代数: 88, 计算机: 69]
南京职业技术学院: 胡长 st008[总分:299, 英语: 69, 化学: 86, 代数: 75, 计算机: 69]
南京职业技术学院: 张杂 st012[总分:298, 英语: 44, 化学: 66, 代数: 99, 计算机: 89]
南京职业技术学院: 邹家 st009[总分:292, 英语: 84, 化学: 69, 代数: 90, 计算机: 49]
南京职业技术学院: 林世 st007[总分:291, 英语: 55, 化学: 78, 代数: 90, 计算机: 68]
南京职业技术学院: 宁可 st011[总分:279, 英语: 67, 化学: 87, 代数: 69, 计算机: 56]
南京职业技术学院:[达标] 当前录取8/总名额(无限制)
未被录取:张质 st023[总分:240, 英语: 87, 化学: 57, 代数: 48, 计算机: 48]
未被录取:王等 st014[总分:233, 英语: 56, 化学: 78, 代数: 88, 计算机: 11]
未被录取:杨角 st015[总分:209, 英语:  0, 化学: 44, 代数: 66, 计算机: 99]

你可能感兴趣的:(xml)