阿里-测试工程师面试题目及答案

题目一:

linux如何实现凌晨定时执行脚本?

Linux中,周期执行的任务一般由cron这个守护进程来处理。cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间。cron的配置文件称为“crontab”,是“cron table”的简写。

题目二:

java如何实现多线程?线程的状态有哪些?

java实现多线程有两种方法

  • 1、继承Thread类
  • 2、实现Runnable接口 这两种方法的共同点: 不论用哪种方法,都必须用Thread(如果是Thead子类就用它本身)产生线程,然后再调用start()方法。

两种方法的不同点:

  • 1、继承Thread类有一个缺点就是单继承,而实现Runnable接口则弥补了它的缺点,可以实现多继承
  • 2、继承Thread类必须如果产生Runnable实例对象,就必须产生多个Runnable实例对象,然后再用Thread产生多个线程;而实现Runnable接口,只需要建立一个实现这个类的实例,然后用这一个实例对象产生多个线程。即实现了资源的共享性

线程共有6种状态:

NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
分别对应于
新建、运行、阻塞、等待、带超时的等待、终止

题目三:

如何做能保证线程安全?(进程安全是什么?)

线程安全 一般说来,确保线程安全的方法有这几个: 竞争与原子操作、同步与锁、可重入、过度优化。

  • 竞争与原子操作 多个线程同时访问和修改一个数据,可能造成很严重的后果。出现严重后果的原因是很多操作被操作系统编译为汇编代码之后不止一条指令,因此在执行的时候可能执行了一半就被调度系统打断了而去执行别的代码了。一般将单指令的操作称为原子的(Atomic),因为不管怎样,单条指令的执行是不会被打断的。 因此,为了避免出现多线程操作数据的出现异常,Linux系统提供了一些常用操作的原子指令,确保了线程的安全。但是,它们只适用于比较简单的场合,在复杂的情况下就要选用其他的方法了。

  • 同步与锁 为了避免多个线程同时读写一个数据而产生不可预料的后果,开发人员要将各个线程对同一个数据的访问同步,也就是说,在一个线程访问数据未结束的时候,其他线程不得对同一个数据进行访问。 同步的最常用的方法是使用锁(Lock),它是一种非强制机制,每个线程在访问数据或资源之前首先试图获取锁,并在访问结束之后释放锁;在锁已经被占用的时候试图获取锁时,线程会等待,直到锁重新可用。 二元信号量是最简单的一种锁,它只有两种状态:占用与非占用,它适合只能被唯一一个线程独占访问的资源。对于允许多个线程并发访问的资源,要使用多元信号量(简称信号量)。

  • 可重入 一个函数被重入,表示这个函数没有执行完成,但由于外部因素或内部因素,又一次进入该函数执行。一个函数称为可重入的,表明该函数被重入之后不会产生任何不良后果。可重入是并发安全的强力保障,一个可重入的函数可以在多线程环境下放心使用。

  • 过度优化 在很多情况下,即使我们合理地使用了锁,也不一定能够保证线程安全,因此,我们可能对代码进行过度的优化以确保线程安全。 我们可以使用volatile关键字试图阻止过度优化,它可以做两件事:第一,阻止编译器为了提高速度将一个变量缓存到寄存器而不写回;第二,阻止编译器调整操作volatile变量的指令顺序。 在另一种情况下,CPU的乱序执行让多线程安全保障的努力变得很困难,通常的解决办法是调用CPU提供的一条常被称作barrier的指令,它会阻止CPU将该指令之前的指令交换到barrier之后,反之亦然。

题目四:

查询数据库比较慢可能是哪些原因造成的?

  • 1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)
  • 2、I/O吞吐量小,形成了瓶颈效应。
  • 3、没有创建计算列导致查询不优化。
  • 4、内存不足
  • 5、网络速度慢
  • 6、查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)
  • 7、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)
  • 8、sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。
  • 9、返回了不必要的行和列
  • 10、查询语句不好,没有优化