IO密集型是指对IO操作较多的任务。下面以查询一些股票价格任务为例:
YahooFinance.java
public class YahooFinance { public static double getPrice(final String ticker) throws IOException{ final URL url = new URL("http://ichart.finance.yahoo.com/table.csv?s=" + ticker); final BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); String discardHeader = reader.readLine(); System.out.println(discardHeader); String data = reader.readLine(); //Sample of data: //Date,Open,High,Low,Close,Volume,Adj Close //2016-09-05,9.08,9.12,8.98,9.02,16212600,9.02 //System.out.println(data); String[] dataItems = data.split(","); double price = Double.valueOf(dataItems[dataItems.length - 1]); return price; } public static void main(String[] args) throws IOException{ YahooFinance.getPrice("600401.SS"); } }
AbstractCalTotal.java 顺序查询和多线程查询的基类
public abstract class AbstractCalTotal { private static String[] stockArr = { "600401.SS,100", "600120.SS,200", "600728.SS,300", "600268.SS,400", "601258.SS,500", //"AMGN,100", "AMZN,200", "BAC,300", "AAPL,400", "HYGF,500", //"ZHFJ,100", "dlkg,200", "BMY,300", "KDXF,400", "CWSZ,500", //"FZDJ,100", "GDNZ,200", "htdl,300", "zsyh,400", "JLQC,500", //"JMGF,100", "PDJT,200", "GLM,300", "ZGQY,400", "hyjx,500", };//股票代码.上交所(深交所),股票数量 public static Map<String, Integer> readTickers() throws IOException{ Map<String, Integer> stocks = new HashMap<>(); String[] info = null; for(int i = 0 ; i < stockArr.length; i++){ info = stockArr[i].split(","); stocks.put(info[0], Integer.valueOf(info[1])); } return stocks; } public void timeAndComputeValue() throws ExecutionException, InterruptedException, IOException{ long start = System.nanoTime(); Map<String, Integer> stocks = readTickers(); double nav = computeNetAssetValue(stocks); long end = System.nanoTime(); String value = new DecimalFormat("$##,##0.00").format(nav); System.out.println("Total net asset value: " + value); System.out.println("Time (seconds) taken: " + (end - start)/1.0e9); } public abstract double computeNetAssetValue(Map<String, Integer> stocks) throws ExecutionException, InterruptedException, IOException; }
顺序查询
public class SequentialCal extends AbstractCalTotal{ @Override public double computeNetAssetValue(Map<String, Integer> stocks)throws IOException { double values = 0.0; for(String ticker : stocks.keySet()){ values += stocks.get(ticker)* YahooFinance.getPrice(ticker); } return values; } public static void main(String[] args)throws ExecutionException, InterruptedException, IOException{ new SequentialCal().timeAndComputeValue(); } }
多线程查询
//调整 blockingCoefficient,可找出较少的执行时间 public class ConcurrentCal extends AbstractCalTotal{ public double computeNetAssetValue(final Map<String, Integer> stocks) throws ExecutionException, InterruptedException, IOException { int numberOfCores = Runtime.getRuntime().availableProcessors(); double blockingCoefficient = 0.9; final int poolSize = (int)(numberOfCores / (1 - blockingCoefficient)); System.out.println("Pool size is: " + poolSize); List<Callable<Double>> partitions = new ArrayList<>(); for(final String ticker : stocks.keySet()){ partitions.add(new Callable<Double>(){ public Double call() throws Exception{ return stocks.get(ticker) * YahooFinance.getPrice(ticker); } }); } final ExecutorService executorPool = Executors.newFixedThreadPool(poolSize); final List<Future<Double>> valueOfStocks = executorPool.invokeAll(partitions, 100, TimeUnit.SECONDS); double netAssetValue = 0.0; //每次循环只能取到一个子任务的结果,且子任务的顺序与我们创建的顺序是一致的。 for(final Future<Double> vas : valueOfStocks){ netAssetValue += vas.get(); //vas.get() 如果此任务尚未完成,程序会等待 } executorPool.shutdown(); return netAssetValue; } public static void main(String[] args)throws ExecutionException, InterruptedException, IOException{ new ConcurrentCal().timeAndComputeValue(); } }