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);
- }
- }