并行测试的一些概念和并行编程(Java代码实现)

2018-06-20

今天学习的主题主要是并行测试。

因为对并行的概念还不是太了解,因此翻阅了计算机操作系统这本书,这本书中对于并行是这样阐述的:

在操作系统的基本特性中,有一个特性叫做并发性,而并行性和并发性是既相似又互相区别的两个概念:

并行性是指两个或多个事件在同一时刻发生,而并发性是指两个或多个事件在同一时间间隔内发生。

再来了解一下并行测试的概念,这里参考了一篇文献《并行测试技术综述 》

并行测试是建立在并行概念基础之上的,并行测试的核心是可以对多个被测对象进行测试。UUT(unit under test)被测试模块。

  • 多个UUT的并行测试实现方式:

1.通过接口开关转换测试:先连接第一个 UUT进行测试,在处理器对测试信号进行分析处 理等操作的同时,接口开关断开第一 个 UUT,将另一 UUT 连接到 ATS进行测试; 依次类推到多个 UUT。

优点:

这种并行测试实现方法通过转换开关使得测试系统在整个测试过程中始终处于非空闲状态,系统的测试吞吐量成倍提高。 UUT可以处于不同的测试区域,加上配套的网络设备,可 以实现分布式并行测试,实现 ATS的共享。实际上,这种方式在某一时刻, ATS只测试某一个 UUT执行一项测试任务,还不是真正意义上的并行测试。

缺点:

扫描二维码关注公众号,回复: 3430864 查看本文章

每项测试均需是独立的,它无需上一项测试的结果,测试结果也不会影响到下一项测试,系统容易出现死锁。

2.并发测试:

真正意义上的并行测试,主要是建立在一个分布式测试系统上,每个测试节点都可以独立进行一个测试[ 7~ 9] 。缺点是需要增加许多额外测试设备,而且需避免复杂的资源共享问题。

  • 单个UUT的并行测试实现方式:

1.交迭等待并行测试

2.分组并行测试

真正在单个 UUT上的并行测试是同步或异步地运行两个或多个测试程序,完成对多个参数的测量。程序执行第一组测试,即测试 1和测试 2分别在不同的线程内同时执行。第二组内的各项 测试也能同步或异步进行,在不同的线程内同时执行测试 3、测试 6和测试 10,依次类推。之所以要把测试分组,是因为要保证同一组的被测试量具有相同的测试要求,在并行运行的时候不会互相影响。这就要求在 测试需求分析时对测试任务进行分组。

并行测试技术通过对系统资源的优化利用,大大提高了测试系统的测试效率和性价比,其突出表现为:

1)提高 ATS的吞吐率。并行测试系统的主要优势就是能在同一时间内完成多个 UUT的测试任务,从 批量测试的角度提高了系统的吞吐率,从而达到减少测试时间的目的。

2)提高仪器使用效率。并行测试从减少仪器的闲置时间和充分利用仪器资源两个方面来提高仪器的使用效率。如前文所述,并行测试任务不断地运行,申请仪器地使用,仪器一旦闲置就再次被新的测试任务申请使用。在最理想的状态下,整个测试过程中仪器一直处于工作状态。

3)缩减测试时间。并行测试可以同时进行多个测试,在一定时间内,在执行两个测试任务时,并行测试 要能比传统顺序测试测试量提高 50%,但事实上,由于存在多个测试的切换时间,因此一般会低于 50%。

针对上述文献中所提到的进程和线程,同步和异步的概念:

  1. 进程较为典型的定义:
  2. 进程是程序的一次执行。
  3. 进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
  4. 进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。

进程的基本状态:

就绪(Ready)状态

执行(Running)状态

阻塞(Block)状态

进程中一个很重要的概念**PCB(进程控制块),它的作用是使一个在多道程序环境下不能独立运行的程序(含数据)成为一个能够独立运行的基本单位,一个能与其他进程并发执行的进程。**详细阐述如下:

1.作为独立运行基本单位的标志

2.能实现间断性运行方式

3.提供进程管理所需要信息

4.提供进程调度所需要信息

5.实现与其他进程的同步与通信

进程同步:

是对多个相关进程在执行次序上进行协调,使并发执行的诸进程之间按照一定的规则(或时序)共享系统资源,并能很好的相互合作,从而使程序的执行具有可再现性。

生产者-消费者模式

生产者-消费者问题是经典的线程同步问题:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费,为使生产者进程与消费者进程能并发执行,在两者之间设置一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费者进程可从一个缓冲区中取走产品去消费。

//用一个数组buffer来表示上述的具有n个缓冲区的缓冲池
//每投入一个产品时,数组单元指针in+1
//循环缓冲in=(in+1)%n
//缓冲池满(in+1)%n=out,in=out表示缓冲池空
//整型变量counter
int in=0,out=0,count=0;
item buffer[n]
//生产者
void producer(){
while(1){
	produce an item in nextp;
	...
	while(counter==n)
	;
	buffer[in]=nextp;
	in=(in+1)%n;
	counter++;
}
};
//消费者
void consumer()
{
    while(1){
        while(counter==0)
            ;
        nextc=buffer[out];
        out=(out+1)%n;
        counter--;
        consumer the item in nextc;
    }
}

java实现中必须掌握的方法Blocking Queue:

package com.zjn.inter;

public interface Consumer {
    void consume() throws InterruptedException;
}

package com.zjn.inter;

public interface Producer {
    void produce() throws InterruptedException;
}

package com.zjn.impl;

public class Task {
    public int no;
    public Task(int no){
        this.no=no;
    }
}

package com.zjn.model;
//为模型定义抽象工厂方法
public interface Model {
    Runnable newRunnableConsumer();
    Runnable newRunnableProducer();
}

package com.zjn.test;

import com.zjn.inter.Consumer;

abstract class AbstractConsumer implements Consumer,Runnable {
    @Override
    public void run(){
        while (true){
            try {
                consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}

package com.zjn.test;

import com.zjn.inter.Producer;

abstract  class AbstractProducer implements Producer,Runnable {
    @Override
    public void run(){
        while (true){
            try {
                produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}

package com.zjn.test;

import com.zjn.impl.Task;
import com.zjn.inter.Consumer;
import com.zjn.inter.Producer;
import com.zjn.model.Model;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

//把并发和容量控制在缓冲区中
public class BlockingQueueModel implements Model {
    private final BlockingQueue<Task> queue;
    private final AtomicInteger increTaskNo=new AtomicInteger(0);
    public BlockingQueueModel(int cap){
        //LinkedBlockingQueue的队列是lazy-init的
        //但ArrayBlockingQueue在创建时就已经init
        this.queue=new LinkedBlockingDeque<>(cap);
    }

    @Override
    public Runnable newRunnableConsumer() {
        return new ConsumerImpl();
    }

    @Override
    public Runnable newRunnableProducer() {
        return new ProducerImpl();
    }
    private class ConsumerImpl extends AbstractConsumer implements Consumer,Runnable{

        @Override
        public void consume() throws InterruptedException {
            Task task=queue.take();
            //固定时间范围的消费,模拟相对稳定的服务器处理过程
            Thread.sleep(500+(long)(Math.random()*500));
            System.out.println("consume:"+task.no);
        }

    }
    private class ProducerImpl extends AbstractProducer implements Producer,Runnable{

        @Override
        public void produce() throws InterruptedException {
             //不定期生产,模拟随机的用户请求
            Thread.sleep((long)(Math.random()*1000));
            Task task=new Task(increTaskNo.getAndIncrement());
            queue.put(task);
            System.out.println("produce:"+task.no);
        }
    }
    public static void main(String[] args){
        Model model=new BlockingQueueModel(3);
        for(int i=0;i<2;i++){
            new Thread(model.newRunnableConsumer()).start();
        }
        for(int i=0;i<5;i++){
            new Thread(model.newRunnableProducer()).start();
        }
    }
}

参考博文:http://www.importnew.com/27063.html

猜你喜欢

转载自blog.csdn.net/nicezheng_1995/article/details/80752502