七牛云笔试(A卷):
1.单选题13题
-
关于网络的协议HTTP,UDP,TCP,ICMP,DNS等
-
关于数据库MySQL的SQL语句处理顺序,脏读幻读,事务等
-
关于排序算法的时间复杂度,空间复杂度,优势和劣势
-
计算机操作系统的fork,进程与线程切换等等
-
Java的gc对象复活
2.多选题5题
-
多线程相关题,阻塞的情况sleep,wait等
-
hash的开放地址法与链地址法
-
红黑树,二叉树,二叉搜索树
-
跳表
-
浏览器输入网址,产生的网络协议有哪些
3.编程题2题
import java.util.Scanner;
public class Test1 {
public static int[] parent;
public static int n, m, sum;
//开始时每个集合只有自己,所以集合老大也是自己
public static void Init() {
parent = new int[n + 1];
for (int i = 1; i <= n; i++)
parent[i] = i;
return;
}
//获得该集合的老大,带路径压缩
public static int get_boss(int v) {
if (parent[v] == v)
return v;
else {
parent[v] = get_boss(parent[v]);
return parent[v];
}
}
//合并两个集合
public static void Merge(int v, int u) {
int t1 = get_boss(v);
int t2 = get_boss(u);
parent[t2] = t1;
return;
}
//并查集
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
Init();
for (int i = 0; i < m; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
Merge(a, b);
}
int count = 0;
for (int i = 1; i <= n; i++) {
if (parent[i] == i) {
count++;
if (count > 1) {
System.out.println("NO");
return;
}
}
}
System.out.println("YES");
return;
}
}
import java.util.Scanner;
import java.util.Stack;
public class Test2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while (n-- > 0){
String s = sc.next();
Stack<Character> stack = new Stack<>();
int len = s.length();
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if (stack.isEmpty()){
stack.push(c);
}else{
char tmp = stack.peek();
if (tmp == c){
stack.pop();
}else {
stack.push(c);
}
}
}
if (stack.isEmpty()){
System.out.println("Yes");
}else{
System.out.println("No");
}
}
}
}
4.综合题1题
阅读以下代码,
public class BankAccount {
private long balance;
public BankAccount(long balance) {
this.balance = balance;
}
static void transferFrom(BankAccount source, BankAccount dest, long amount) {
synchronized(BankAccount.class) {
source.balance -= amount;
dest.balance += amount;
}
}
public synchronized long balance() {
return balance;
}
}
工程师小明,考虑到这样的实现对性能不太友好,于是重构了一版transferFrom方法:
static void transferFrom(BankAccount source, BankAccount dest, long amount) {
synchronized(source) {
synchronized(dest) {
source.balance -= amount;
dest.balance += amount;
}
}
}
小明觉得,这样的实现好极了,因为它降低了锁的粒度。小明为自己能够熟练运用多线程并发编程技术感到非常开心,但是当他提交了代码,同事老王在review代码说,这样的改写在并发情况下有问题,要求回去好好改改。假如你是小明,请解释上面代码存在的潜在问题并描述修改方案,并修改上面的代码(提示,BankAccount类可以根据需要更改,只要能够在多线程环境下完成“转账”功能即可):
(1)解释&修改方案 (5分)
(2)更改后的代码 (10分)