本文面向对象:测试开发工程师(服务端自动化方向)。
随手百度一下都能找到**岗位面试总结,但是有关测开岗位的面试总结却寥寥无几。总体原因可能是这两个:
1 测试行业整体水平参差不齐,导致不同公司面试的问题不能抽象出来写概览。
2 很多做测开的人可能内心对这个行业缺少热爱,所以不爱去写。
在找工作的过程中发现测开被问到的非常杂,涵盖了Python/Java基础(我平时使用Java语言较多)、算法、测试基础、Linux基本命令、测试工具selenium等。现在把以上五个方面分五篇总结。
Java基础
3.一般面试官问到线程安全问题都会把多线程、线程同步、线程安全等考虑进来,我们一个个来说
多线程
线程:线程是指进程中一个单一顺序的控制流。一个进程可以并发多个线程。每条线程执行不同的任务。
线程创建的方法
线程创建的几种方法:
1,继承Thread类并重写run方法
2,采用实现Runnable接口创建多线程,3,通过Callable和Future创建线程。
深入问的话会问到两种情况:
1 多线程具体是如何实现的,继承Thread类并创建一个该类的实例并重写run方法,该方法是新线程的入口,同时也必须调用start()方法执行,执行顺序是creating thread -> start thread -> running thread. 实现runnable接口来创建多线程的顺序也是类似。
2实现Runnable接口和使用Callable接口的相似之处、不同之处:
Callable接口类似于Runnalble,都是为了实例可能被另一个线程所执行的类而设计;
不同点:1. Callable可以截获异常并有返回值 2.Callable需要依赖FutureTask实现。
线程同步实现的几种方式
多线程会导致线程不安全问题出现,也就是说多个线程并发执行并操作同一可同享的资源变量时可能会导致数据不一致的情况(常见的卖票的情况),因此需要线程同步,线程同步实现的方式有以下几种:
一、使用synchronized关键字修饰方法:
public static synchronized void save(){}
注:使用static表示要锁住 整个类
二、同步代码块synchronized(Object object ){}
/**
*使用同步代码块实现方法
**/
public void save(int money){
synchronized(this){
account+=money;
}
}
三、 使用volatile关键字实现同步
volatile比较特殊,首先,它为域变量的访问提供了一种免锁机制,使用volatile修饰相当于高速虚拟机该域可能会被其他线程更新,因为每次使用该域要重新计算,而不是使用寄存器中的值。volatile不能保证变量的原子性,所以一般不会用在频繁写操作中。
(volatile关键字的原理很可能会被问到,即volatile不用锁是怎么实现同步的:原理是每次要线程要访问volatile修饰的变量时都是从内存中读取,而不是存缓存当中读取,因此每个线程访问到的变量值都是一样的。这样就保证了同步。)
class Bank{
private volatile int account=100;
public void save(int money){
account+=money;
}
}
四、使用重入锁实现线程同步
Java5之后新增了concurrent包支持同步,R恩恩突然跳Lock类可重入、互斥、实现了Lock接口的锁,其使用方法见代码:
/**
*ReenreantLock类的常用方法:创建一个ReentrantLock实例 *lock() : 获得锁 unlock() : 释放锁
**/
class Bank{
private int account=100;
private Lock lock=new ReentrantLock();
public int getAccount(){
return account;
}
public void save(int money){
lock.lock();
try{
account+=money;
}finally{
lock.unlock();
}
}
}
五、使用局部变量ThreadLocal实现线程同步
ThreadLocal的原理:如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。现在明白了吧,原来每个线程运行的都是一个副本,也就是说存钱和取钱是两个账户,只是名字相同而已。所以就会发生上面的效果。
class Bank{
private static private static ThreadLocal count = new ThreadLocal(){
@Override
protected Integer initialValue() {
// TODO Auto-generated method stub
return 0;
}
};
public void save(int money){
account+=money;
}
}
线程的几种状态
线程的生命周期包含:新建状态/就绪状态/运行状态/阻塞状态/死亡状态。其中阻塞状态可以分为三种:等待阻塞 运行状态中的线程执行wait()方法,使线程进入到等待阻塞;同步阻塞 线程获取synchronized同步锁失败,同步锁被其他线程占用;其他阻塞 调用线程的sleep()或join()发出I/O请求时,线程进入到阻塞状态。sleep()超时活着join()等待线程终止或者超时,或者I/O处理完毕,线程重新转入就绪状态。
4.输入输出流io考点
有哪些常用的输入输出流
举例 字节流 字符流 字节流:InputStream OutputStream 字符流:Reader Writer
流按照传输方向可以分为哪些
输入输出是相对程序而言,输入流InputStream读入文件;输出流OutputStream写文件。
常用的io流
InputStream,OutputStream,
FileInputStream,FileOutputStream,
BufferedInputStream,BufferedOutputStream
Reader,Writer
BufferedReader,BufferedWriter
例:结合多线程和输入输出流,开启三个线程同时读取A B C文件,并且写入D文件(考虑线程同步的情况)。