多线程中共享变量——CCF总决赛试题
Posted 静若飘絮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程中共享变量——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毫秒
以上是关于多线程中共享变量——CCF总决赛试题的主要内容,如果未能解决你的问题,请参考以下文章