java并发计算素数,时间可以大幅度提高

Java并发是个很常用的知识点。面试基本上是必问,工作中也常用。

并发的风险:
1,程序饥饿,比如一个程序运行的时候要得到操作员的确认,但是操作员吃饭去了,这个程序将一直处于等待状态。
2,死锁:相互等待对方所占有的资源。
3,资源竞争:两个程序竞争相同的资源。
举个栗子:计算一个范围内素数的个数,首先是用常用的顺序计算,然后用多线程进行计算。比较两者的执行效率。下面是一个工具类,顺序计算和多线程计算都要用到。

[java]  view plain  copy
  1. package com.sunyard.demo.concurrency;  
  2.   
  3. /** 
  4.  * 此类作为工具类 
  5.  */  
  6. public abstract class AbstractPrimeFinder {  
  7.     /** 
  8.      * 判断一个数是否为素数 
  9.      * @param number 
  10.      * @return 
  11.      */  
  12.     public boolean isPrime(final int number){  
  13.         if(number <= 1return false;  
  14.         for(int i=2;i<=Math.sqrt(number);i++)  
  15.             if(number % i==0return false;  
  16.             return true;  
  17.     }  
  18.   
  19.     /** 
  20.      * 计算一个区间内的素数的个数 
  21.      * @param lower 
  22.      * @param upper 
  23.      * @return 
  24.      */  
  25.     public int countPrimesInRange(final int lower,final int upper){  
  26.         int total=0;  
  27.         for (int i=lower;i<=upper;i++)  
  28.             if(isPrime(i)) total++;  
  29.         return total;  
  30.     }  
  31.   
  32.     /** 
  33.      * 统计程序计算素数所花费的时间 
  34.      * @param number 
  35.      */  
  36.     public void timeAndCompute(final int number){  
  37.         final long start = System.nanoTime();  
  38.         final long numberOfPrimes=countPrimes(number);  
  39.         final long end = System.nanoTime();  
  40.         System.out.printf("Number of primes under %d is %d\n",number,numberOfPrimes);  
  41.         System.out.println("Time (seconds) taken is:"+(end-start)/1.0e9);  
  42.     }  
  43.     public abstract int countPrimes(final int number);  
  44. }  
单线程的情况如下:

[java]  view plain  copy
  1. package com.sunyard.demo.concurrency;  
  2.   
  3. /** 
  4.  * 启动类 
  5.  */  
  6. public class SequentialPrimeFinder extends AbstractPrimeFinder {  
  7.     /** 
  8.      * 实现父类中的方法 
  9.      * @param number 
  10.      * @return 
  11.      */  
  12.     @Override  
  13.     public int countPrimes(final int number) {  
  14.         return countPrimesInRange(1,number);  
  15.     }  
  16.     /** 
  17.      * 程序主方法 
  18.      * @param args 
  19.      */  
  20.     public static void main(String[] args){  
  21.         //计算的区间为1到10000000  
  22.         new SequentialPrimeFinder().timeAndCompute(10000000);  
  23.     }  
  24. }  


多线程如下:

[java]  view plain  copy
  1. public class ConcurrentPrimeFinder extends AbstractPrimeFinder {  
  2.     private final int poolSize;//创建线程的个数  
  3.     private final int numberOfParts;//任务的份数  
  4.   
  5.     /** 
  6.      * 构造方法初始化线程的个数和任务的划分 
  7.      * @param poolSize 
  8.      * @param numberOfParts 
  9.      */  
  10.     public ConcurrentPrimeFinder(final int poolSize, final int numberOfParts) {  
  11.         this.poolSize = poolSize;  
  12.         this.numberOfParts = numberOfParts;  
  13.     }  
  14.   
  15.     @Override  
  16.     public int countPrimes(final int number) {  
  17.         int count=0;//统计各区间的素数个数  
  18.         try {  
  19.             final List<Callable<Integer>> partitions=new ArrayList<Callable<Integer>>();  
  20.             final int chunksPerPartion=number /numberOfParts;  
  21.             for(int i=0; i<numberOfParts;i++){  
  22.                 final int lower=(i*chunksPerPartion)+1;  
  23.                 final int upper=(i==numberOfParts-1)? number:lower+chunksPerPartion-1;  
  24.                 partitions.add(new Callable<Integer>() {  
  25.                     @Override  
  26.                     public Integer call() {  
  27.                         return countPrimesInRange(lower,upper);  
  28.                     }  
  29.                 });  
  30.             }  
  31.             final ExecutorService executorPool= Executors.newFixedThreadPool(poolSize);//在线程池中创建线程  
  32.             final List<Future<Integer>> resultFromParts=executorPool.invokeAll(partitions,10000,TimeUnit.SECONDS);  
  33.             executorPool.shutdown();//执行完成之后关闭线程池  
  34.             for(final Future<Integer> result:resultFromParts)//统计各任务的素数个数  
  35.                 count +=result.get();  
  36.         }catch (Exception ex){  
  37.             throw new RuntimeException(ex);  
  38.         }  
  39.         return count;  
  40.     }  
  41.     public static void main(String[] args){  
  42.         new ConcurrentPrimeFinder(4,4).timeAndCompute(10000000);  
  43.     }  
  44. }  


猜你喜欢

转载自blog.csdn.net/Com_ma/article/details/80784544