《Java程序性能优化》之并发优化

第四章 并行程序优化

1.非阻塞同步避免了基于锁的同步的缺陷,无锁算法没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销。
CAS算法:包含3个参数CAS(v,e,n)。V表示要更新的变量,E表示预期值,N表示新值
2.JDK的java.util.concurrent.atomic包下,有一组使用无锁算法实现的原子操作类,如AtomicInteger/AtomicIntegerArray/AtomicLongArray等,

分别包装了对整数、整数数组、长整形数组等的多线程安全操作。

如:

public class AtomicTest {

    public static final int MAX_THREADS=3; 
    public static final int TASK_COUNT=3; 
    public static final int TARGET_COUNT=10000; 
    private AtomicInteger account=new AtomicInteger(0);//无锁的原子操作数量
    private int  count=0;
    
    //有锁的加法
    private synchronized int add() {
        return count++;
    }
    
    //有锁的操作
    private synchronized int getCount() {
        return count;
    }
    
    //实现有锁操作的内部类
    public class SynchThread implements Runnable{
        
        protected String name;
        protected long starttime;
        AtomicTest out;
        public  SynchThread(AtomicTest o,long starttime) {
            out=o;
            this.starttime=starttime;
        }

        @Override
        public void run() {
            int v=out.add();//有锁的加法
            while (v<TARGET_COUNT) {
                v=out.add();//达到目标值前,不停的循环
            }
            long endtime=System.currentTimeMillis();//系统当前时间 精确到ms
            System.out.println("SynchThread spend:"+(endtime-starttime)+"ms");
        }
    }
    //实现原子操作的内部类
    public class AtomicThread implements Runnable{
        
        protected long starttime;
        
        public AtomicThread(long starttime){
            this.starttime=starttime;
        }
        
        @Override
        public void run() {
            int v=account.incrementAndGet();
            while(v<TARGET_COUNT){
                v=account.incrementAndGet();
            }
            long endtime=System.currentTimeMillis();
            System.out.println("AtomicThread spend:"+(endtime-starttime)+"ms");
        }    
    }
    
    /**
     * JUnit方法测试
     * @throws InterruptedException
     */
    @Test
    public void testAtomic() throws InterruptedException {
        ExecutorService exe=Executors.newFixedThreadPool(MAX_THREADS);//初始化三个线程
        long starttime=System.currentTimeMillis();
        AtomicThread atomic=new AtomicThread(starttime);
        
        for(int i=0;i<TARGET_COUNT;i++){
            exe.submit(atomic);//提交三个线程开始工作
        }
        Thread.sleep(1000);//重新分配
    }

//    @Test
    public void testSynch() throws InterruptedException {
        ExecutorService exe=Executors.newFixedThreadPool(MAX_THREADS);
        long starttime=System.currentTimeMillis();
        SynchThread synch=new SynchThread(this,starttime);
        
        for(int i=0;i<TARGET_COUNT;i++){
            exe.submit(synch);
        }
        Thread.sleep(1000);
        //检测线程池是否关闭
        System.out.println(exe.isTerminated());
        }
}

第五章 JVM调优

1.JVM虚拟机将其内存数据分为程序计数器、虚拟机栈,本地方法栈,Java堆,和方法去等部分。

2.Java虚拟机栈,在Java 虚拟机规范中,定义了两种异常与占空间相关,即StackOverError和OutOfMemoryError。如果线程在计算过程中,请求的栈深度大于最大可用的栈深度,则抛出SOE,如果Java栈可以动态扩展,而在扩展栈的过程中,没有足够的内存空间来支持栈的扩展,则抛出OutOfMemoryError。
栈的大小直接决定了函数调用的可达深度。
如:

public class StackOverTest {
    private int count=0;
    public void recursion(){//没有出口的递归函数
        count ++;         //计数加一
        recursion();
    }
    
    @Test
    public void stest(){
        try{
            recursion();//递归调用
        }catch(Throwable t){
            //打印栈的深度
            System.out.println("the depth of stack is "+count);
            t.printStackTrace();
        }
    }
}

 使用-Xss修改栈的大小后,函数调用深度明显上升。

 

原文地址:https://www.cnblogs.com/binyue/p/3913003.html