java多线程计算素数

来源:互联网 发布:淘宝手机详情有用吗 编辑:程序博客网 时间:2024/06/07 15:00

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

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

package com.sunyard.demo.concurrency;/** * 此类作为工具类 */public abstract class AbstractPrimeFinder {    /**     * 判断一个数是否为素数     * @param number     * @return     */    public boolean isPrime(final int number){        if(number <= 1) return false;        for(int i=2;i<=Math.sqrt(number);i++)            if(number % i==0) return false;            return true;    }    /**     * 计算一个区间内的素数的个数     * @param lower     * @param upper     * @return     */    public int countPrimesInRange(final int lower,final int upper){        int total=0;        for (int i=lower;i<=upper;i++)            if(isPrime(i)) total++;        return total;    }    /**     * 统计程序计算素数所花费的时间     * @param number     */    public void timeAndCompute(final int number){        final long start = System.nanoTime();        final long numberOfPrimes=countPrimes(number);        final long end = System.nanoTime();        System.out.printf("Number of primes under %d is %d\n",number,numberOfPrimes);        System.out.println("Time (seconds) taken is:"+(end-start)/1.0e9);    }    public abstract int countPrimes(final int number);}
单线程的情况如下:

package com.sunyard.demo.concurrency;/** * 启动类 */public class SequentialPrimeFinder extends AbstractPrimeFinder {    /**     * 实现父类中的方法     * @param number     * @return     */    @Override    public int countPrimes(final int number) {        return countPrimesInRange(1,number);    }    /**     * 程序主方法     * @param args     */    public static void main(String[] args){        //计算的区间为1到10000000        new SequentialPrimeFinder().timeAndCompute(10000000);    }}


多线程如下:

public class ConcurrentPrimeFinder extends AbstractPrimeFinder {    private final int poolSize;//创建线程的个数    private final int numberOfParts;//任务的份数    /**     * 构造方法初始化线程的个数和任务的划分     * @param poolSize     * @param numberOfParts     */    public ConcurrentPrimeFinder(final int poolSize, final int numberOfParts) {        this.poolSize = poolSize;        this.numberOfParts = numberOfParts;    }    @Override    public int countPrimes(final int number) {        int count=0;//统计各区间的素数个数        try {            final List<Callable<Integer>> partitions=new ArrayList<Callable<Integer>>();            final int chunksPerPartion=number /numberOfParts;            for(int i=0; i<numberOfParts;i++){                final int lower=(i*chunksPerPartion)+1;                final int upper=(i==numberOfParts-1)? number:lower+chunksPerPartion-1;                partitions.add(new Callable<Integer>() {                    @Override                    public Integer call() {                        return countPrimesInRange(lower,upper);                    }                });            }            final ExecutorService executorPool= Executors.newFixedThreadPool(poolSize);//在线程池中创建线程            final List<Future<Integer>> resultFromParts=executorPool.invokeAll(partitions,10000,TimeUnit.SECONDS);            executorPool.shutdown();//执行完成之后关闭线程池            for(final Future<Integer> result:resultFromParts)//统计各任务的素数个数                count +=result.get();        }catch (Exception ex){            throw new RuntimeException(ex);        }        return count;    }    public static void main(String[] args){        new ConcurrentPrimeFinder(4,4).timeAndCompute(10000000);    }}



原创粉丝点击