ホワイトボックステストで本格的な同時テストを実現する方法(Java)

7426 ワード

この話題が始まる前に、まずなぜ同時テストをするのかを明らかにしましょう.
一般的な同時テストとは、アナログ同時アクセスを指し、複数のユーザーが同じアプリケーション、モジュール、データに同時アクセスしたときに、メモリ漏洩、スレッドロック、リソース競合などの隠れた同時問題が発生するかどうかをテストします.
パフォーマンステストの観点から、同時テストはパフォーマンス指標を得るためではなく、同時発生の問題を発見するためです.
では,同時対応技術の実現はいったいどのようなものなのか.
簡単に言えば、コンカレントとは、複数のプロセスまたはスレッドが特定の操作を同時に処理することを意味し、パフォーマンステストにおける集合点の概念に似ており、同時性にこだわっている.
ここに普及し、次に技術の実現について議論する.
最近、プロジェクトの中でいくつかの開発者が動的テストシミュレーション500を同時に行うことを発見したとき、実現コードは以下の通りである.
コードクリップ1:
public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(int i=0;i<500;i++){
            new MyThread().run();
        }
    }

    static class MyThread implements Runnable{

        @Override
        public void run() {
            // TODO Auto-generated method stub
            //                
        }
    }

共有オブジェクトの使用に関連するため、マルチスレッドの乱れを避けるため、同期ロックを追加することをお勧めします.その後、開発者はコードを書き換え、以下のように実現しました.
コードクリップ2:
public static void main(String[] args) {
        // TODO Auto-generated method stub
        //      ,  500    
        ThreadPoolExecutor executor = new ThreadPoolExecutor(500, 500, 1000,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue(500),
                new ThreadPoolExecutor.DiscardOldestPolicy());

        for(int i=0;i<500;i++){
            executor.execute(new MyThread());
        }

        executor.shutdown();
    }

    static class MyThread implements Runnable{

        @Override
        public void run() {
            // TODO Auto-generated method stub
            //                
            synchronized (this) {

            }
        }
    }

実はこの方式はCPUレベルでFIFO戦略(先进先出)を采用しており、スレッドは顺次ロックリソースを手に入れて処理するので同时性に达することはできないので、私は自分でホワイトボックステストをすることにした.以下の2つの方式で実现する:CyclicBarrierとCountDownLatch.
コードクリップ3:
public static void main(String[] args) {
        // TODO Auto-generated method stub
        CountDownLatch cdl = new CountDownLatch(500);
        for (int i = 0; i < 500; i++) {
            new MyThread(cdl).run();
        }
        try {
            cdl.await();//  await()         ,      count  0     
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    static class MyThread implements Runnable {
        private CountDownLatch cdl;

        public MyThread(CountDownLatch cdl) {
            this.cdl = cdl;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            cdl.countDown();// count  1
            //                
        }
    }

上の各スレッドはカウンタを共有しており、1を減らした後await()メソッドを呼び出して保留し、countが0に減るまで一緒に実行し続けます.
コードクリップ4:
public static void main(String[] args) {
        // TODO Auto-generated method stub
        CyclicBarrier cb = new CyclicBarrier(500);
        ExecutorService es = Executors.newFixedThreadPool(500);
        for (int i = 0; i < 500; i++) {
            es.execute(new MyThread(cb));
        }
        es.shutdown();
    }

    static class MyThread implements Runnable {
        private CyclicBarrier cb;

        public MyThread(CyclicBarrier cb) {
            this.cb = cb;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                //           
                cb.await();
                //                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

すべてのスレッドが作成された後、await()メソッドを呼び出して、すべてのスレッドがbarrier状態に達するまで同時に実行します.
声明:ここで、CyclicBarrierのbarrier状態は再利用可能であり、CountDownLatchは再利用不可であり、個人的にはCyclicBarrierをお勧めします.性能上の損失が小さいからです.
今日はここまでにまとめました~~