• 多线程中共享变量——CCF总决赛试题


    题目要求

    数据格式

    Q 系统的输入为纯文本格式的文件,由若干行组成,每一行由城市编号、年龄、收入组成,相邻两项之间用一个空格分隔。以下是输入的一个片段:

    1001 20 12000

    1001 50 24200

    1020 30 30000

    其中,城市编号是四位数(第一位不为 0),年龄与收入为整数类型。

    查询描述

    Q 系统需要实现以下三个常用的查询功能:

    • Q1: 查询城市 X 某个年龄段的平均收入;
    • Q2: 查询城市 X 的收入最高的前 K 位的收入;
    • Q3: 分别查询某些城市某一年龄段收入的中位数。

    一、下面的程序使用多线程比单线程快了将近一倍。

    下面代码简化了输入过程,让输入的数据提前确定好,便于看时间的效率。

    import java.io.*;
    import java.math.BigInteger;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Scanner;
    class My_Thread implements Runnable{
        public File file=new File("src/xian/chen01/city.txt"); /*city.txt中存放数据*/
        public BufferedReader reader = null;
        public List<Integer> list=null;
        public List<Integer> n_list=null; /*List方便排序*/
        public int line=0;
        public int n_line=0;
        public int k=50;
        public String x_number="1001";
        public String n_number="1001";
        public int n_age=20;
        public BigInteger age=null;
        public int back=0;
        public long t1=0;
         public My_Thread(){
             t1=System.currentTimeMillis();
            try{
             reader = new BufferedReader(new FileReader(file));
             list=new ArrayList<Integer>();
             n_list=new ArrayList<Integer>();
             age=new BigInteger("0");
            }catch(Exception e){}
        }
        @Override
        public void run() {  
    /*此处代码是核心,加锁避免了java.io.IOException: Stream closed 问题*/
            synchronized (this) {
                if(back==0)
                    hui();   /*取出文件的内容*/ 
                else
                {    if(back==1)
                      print();   /*打印结果*/
                    else
                        return ;
                }
            }    
        }
        public synchronized void hui (){
            try{
            //long t1=System.currentTimeMillis();
            
             String tempString = null;
             while ((tempString =reader.readLine())!=null) {
                 String str[]=tempString.split(" ");
                 if(x_number.equals(str[0]))
                 {
                     age=age.add(new BigInteger(str[1]));
                     int a=Integer.parseInt(str[2]);
                     list.add(a);
                     line ++ ;
                 }    
                 if(n_number.equals(str[0])&&(n_age+"").equals(str[1]))
                 {
                     n_list.add(Integer.parseInt(str[2]));
                     n_line++;
                 } 
             }
             reader.close();
             back=1;
            }catch(Exception e){
                System.out.println(e);
            }
        };
        public synchronized void print(){
             Comparator<Integer> comparator = new Comparator<Integer>()
             {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2-o1;   /*降序*/
                }
              };
             if(line>0)
             {
               age=age.divide(new BigInteger(line+""));
               Collections.sort(list,comparator);
               System.out.println("该城市的总人数:"+line);
               System.out.println("list的大小:"+list.size());
               System.out.println("该城市的平均年龄:"+age);
               System.out.print("该城市的前k位收入是:");
               for(int i=0;i<k&&i<list.size();++i)
               System.out.print(list.get(i)+"、");
               System.out.println();
             }
             else
                 System.out.println("该城市编号不存在");
             /*下面是求某个城市的年龄段的中位数收入*/
             System.out.print("编号n城市中位数是:");
             if(n_line>0)
             {
                 Collections.sort(n_list,comparator);
                 if(n_line%2==1)
                     System.out.println(n_list.get(n_line/2));
                 else
                 {
            System.out.println((n_list.get(n_line/2)+n_list.get((n_line-1)))/2);
                 }
             }else
                 System.out.println("编号n城市对应的年龄不存在");
             back=2;
            System.out.println("时间:"+(System.currentTimeMillis()-t1));
        };
    };
    public class Scoket_Q_City_Query2 {
    public static void main(String[] args) throws Exception {
        
      My_Thread thread=new My_Thread();
      new Thread(thread).start();
      new Thread(thread).start();
      new Thread(thread).start();
      new Thread(thread).start();
      new Thread(thread).start(); 
    };
    }

    运行结果:54毫秒

    二、下面是仅仅是一个单线程实现(也可以不建立单线程,只在main主线程实现也可以)

    import java.io.*;
    import java.math.BigInteger;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Scanner;
    class MyThread implements Runnable{
        @Override
        public void run() {
            hui();
        }
        public synchronized void hui (){
            try{
            long t1=System.currentTimeMillis();
             Scanner sc=new Scanner(System.in);
             Comparator<Integer> comparator = new Comparator<Integer>()
             {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2-o1;   /*降序*/
                }
              };
             System.out.print("输入X城市的编号:");
             String x_number=null;
                     //sc.next();
             x_number="1001";
             System.out.print("收入X城市的k值:");
             int k=50;
                     //sc.nextInt();
             System.out.print("输入某个n城市的编号:");
             String n_number="1001";
                     //sc.next();
             System.out.print("输入n城市的某个年龄:");
             int n_age=20;
                     //sc.nextInt();
             sc.close();
             File file=new File("src/xian/chen01/city.txt");
             BufferedReader reader = null;
             String tempString = null;
             BigInteger age=new BigInteger("0");
             int line =0;
             int n_line =0;
             List<Integer> list=new ArrayList<Integer>();
             List<Integer> n_list=new ArrayList<Integer>();
             reader = new BufferedReader(new FileReader(file));
             while ((tempString =reader.readLine())!=null) {
                 String str[]=tempString.split(" ");
                 if(x_number.equals(str[0]))
                 {
                     age=age.add(new BigInteger(str[1]));
                     int a=Integer.parseInt(str[2]);
                     list.add(a);
                     line ++ ;
                 }
                 if(n_number.equals(str[0])&&(n_age+"").equals(str[1]))
                 {
                     n_list.add(Integer.parseInt(str[2]));
                     n_line++;
                 } 
             }
             reader.close();
            
             if(line>0)
             {
               age=age.divide(new BigInteger(line+""));
               Collections.sort(list,comparator);
               System.out.println("该城市的总人数:"+line);
               System.out.println("list的大小:"+list.size());
               System.out.println("该城市的平均年龄:"+age);
               System.out.print("该城市的前k位收入是:");
               for(int i=0;i<k&&i<list.size();++i)
               System.out.print(list.get(i)+"、");
               System.out.println();
             }
             else
                 System.out.println("该城市编号不存在");
             /*下面是求某个城市的年龄段的中位数收入*/
             System.out.print("中位数是:");
             if(n_line>0)
             {
                 Collections.sort(n_list,comparator);
                 if(n_line%2==1)
                     System.out.println(n_list.get(n_line/2));
                 else
                 {
                     
                     System.out.println((n_list.get(n_line/2)+n_list.get((n_line-1)/2))/2);
                 }
             }else
                 System.out.println("编号n城市对应的年龄不存在");
             System.out.println("运行时间:"+(System.currentTimeMillis()-t1));
            }catch(Exception e){}
        };
    };
    public class Scoket_Q_City_Query {
    public static void main(String[] args) throws Exception {
        
      MyThread thread=new MyThread();
      Thread th=new Thread(thread);
      th.start();
    };
    }

    时间:84毫秒

  • 相关阅读:
    golang框架对比Revel and Beego
    Gin框架系列02:路由与参数
    用cp命令拷贝文件,源目录后带不带斜杠的区别
    Isilon Gen6的换盘步骤
    如何在同一行里执行多个linux命令?
    KB,MB,GB,TB,PB,EB,ZB,YB,BB
    Isilon的WebUI上指定跨时区时间的小问题
    用Powershell强制同步Windows主机与Internet time server的时间
    Remote Desktop突然不能用了 “This could be due to CredSSP encryption oracle remediation”
    打开KVM Console的一些注意事项
  • 原文地址:https://www.cnblogs.com/duange/p/6095197.html
Copyright © 2020-2023  润新知