阿裡內部面試總結,阿裡面試總結
1.StringBuffer和StringBuilder有什麼區別?假設有一個方法,方法內部需要定義一個對象,可能是StringBuffer或StringBuilder,接下來會多次append操作,方法結束時,返回這個對象的toString()結果,並且這個線程會被多線程並發訪問,請選擇這個對象是被定義成StringBuffer或者StringBuilder?為什麼?
答:StringBuffer是線程安全的;StringBuilder是線程不安全的。
1.先來看String StringBuffer StringBuilder定義。final修飾的類不能被繼承,即不能擁有子類。
public final class StringBuffer
public final class StringBuilder
public final class String
2.關於appdend方法的源碼如下:
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
3.對於經常變動的字符串才會考慮使用StringBuilder和StringBuffer,使用StringBuilder效率比StringBuffer高,StringBuffer可以保證線程安全,而StringBuilder不能。
2.synchronized有什麼用?如何使用?(偽代碼,把所有使用方式都分別列出來)
答:synchronized是Java語言的關鍵字,同時也是一個可重入鎖。當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多只有一個線程執行該段代碼。synchronized用於修飾方法和代碼塊(對象鎖和成員鎖)。

![]()
package basic;
public final class TestSynchronized {
public static void main(String[] args) {
new Thread("線程A") {
@Override
public void run() {
try {
print("線程A ...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
new Thread("線程B") {
@Override
public void run() {
try {
print("線程B ...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
public static synchronized void print(String str) throws InterruptedException {
System.out.println("當前線程:" + Thread.currentThread().getName() + "執行開始");
for (int i = 0; i < 10; i++) {
System.out.println(str);
Thread.sleep(2000);
}
System.out.println("當前線程:" + Thread.currentThread().getName() + "執行完畢");
}
}
//代碼執行結果:
當前線程:線程A執行開始
線程A ...
線程A ...
線程A ...
線程A ...
線程A ...
線程A ...
線程A ...
線程A ...
線程A ...
線程A ...
當前線程:線程A執行完畢
當前線程:線程B執行開始
線程B ...
線程B ...
線程B ...
線程B ...
線程B ...
線程B ...
線程B ...
線程B ...
線程B ...
線程B ...
當前線程:線程B執行完畢
synchronized修飾方法
synchronized在修飾方法的同時,還可以修飾代碼塊。在修飾代碼塊的時候,分為對象鎖和成員鎖。接下來分別看代碼實現如下:

![]()
package basic;
public class SynchronizedExample {
public static void main(String[] args) {
new Thread("線程A") {
@Override
public void run() {
print("線程A");
}
}.start();
new Thread("線程B") {
@Override
public void run() {
print("線程B");
}
}.start();
}
public static void print(String str) {
System.out.println("線程: " + Thread.currentThread().getName() + "開始執行");
synchronized (SynchronizedExample.class) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "打印了信息:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
System.out.println("線程: " + Thread.currentThread().getName() + "執行結束");
}
}
// 代碼執行結果:
線程: 線程A開始執行
線程A打印了信息:0
線程: 線程B開始執行
線程A打印了信息:1
線程A打印了信息:2
線程A打印了信息:3
線程A打印了信息:4
線程A打印了信息:5
線程A打印了信息:6
線程A打印了信息:7
線程A打印了信息:8
線程A打印了信息:9
線程: 線程A執行結束
線程B打印了信息:0
線程B打印了信息:1
線程B打印了信息:2
線程B打印了信息:3
線程B打印了信息:4
線程B打印了信息:5
線程B打印了信息:6
線程B打印了信息:7
線程B打印了信息:8
線程B打印了信息:9
線程: 線程B執行結束
synchronized 對象鎖 示例代碼(只針對類的當前實例)
接下來再看,

![]()
package basic;
public class SynchronizedExample {
public static void main(String[] args) {
final MySynchronized mySynchronized = new MySynchronized();
new Thread("線程A") {
@Override
public void run() {
mySynchronized.print("線程A");
}
}.start();
new Thread("線程B") {
@Override
public void run() {
mySynchronized.print("線程B");
}
}.start();
}
}
class MySynchronized {
public synchronized void print(String str) {
System.out.println("線程: " + Thread.currentThread().getName() + "開始執行");
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "打印了信息:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("線程: " + Thread.currentThread().getName() + "執行結束");
}
}
//代碼運行結果:
線程: 線程A開始執行
線程A打印了信息:0
線程A打印了信息:1
線程A打印了信息:2
線程A打印了信息:3
線程A打印了信息:4
線程A打印了信息:5
線程A打印了信息:6
線程A打印了信息:7
線程A打印了信息:8
線程A打印了信息:9
線程: 線程A執行結束
線程: 線程B開始執行
線程B打印了信息:0
線程B打印了信息:1
線程B打印了信息:2
線程B打印了信息:3
線程B打印了信息:4
線程B打印了信息:5
線程B打印了信息:6
線程B打印了信息:7
線程B打印了信息:8
線程B打印了信息:9
線程: 線程B執行結束
package basic;
public class SynchronizedExample {
public static void main(String[] args) {
final MySynchronized mySynchronized_first = new MySynchronized();
final MySynchronized mySynchronized_second = new MySynchronized();
new Thread("線程A") {
@Override
public void run() {
mySynchronized_first.print("線程A");
}
}.start();
new Thread("線程B") {
@Override
public void run() {
mySynchronized_second.print("線程B");
}
}.start();
}
}
class MySynchronized {
public synchronized void print(String str) {
System.out.println("線程: " + Thread.currentThread().getName() + "開始執行");
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "打印了信息:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("線程: " + Thread.currentThread().getName() + "執行結束");
}
}
//代碼運行結果:
線程: 線程A開始執行
線程A打印了信息:0
線程: 線程B開始執行
線程B打印了信息:0
線程A打印了信息:1
線程B打印了信息:1
線程A打印了信息:2
線程B打印了信息:2
線程A打印了信息:3
線程B打印了信息:3
線程A打印了信息:4
線程B打印了信息:4
線程A打印了信息:5
線程B打印了信息:5
線程A打印了信息:6
線程B打印了信息:6
線程A打印了信息:7
線程B打印了信息:7
線程A打印了信息:8
線程B打印了信息:8
線程A打印了信息:9
線程B打印了信息:9
線程: 線程A執行結束
線程: 線程B執行結束
package basic;
public class SynchronizedExample {
public static void main(String[] args) {
final MySynchronized mySynchronized_first = new MySynchronized();
final MySynchronized mySynchronized_second = new MySynchronized();
new Thread("線程A") {
@Override
public void run() {
mySynchronized_first.print("線程A");
}
}.start();
new Thread("線程B") {
@Override
public void run() {
mySynchronized_second.print("線程B");
}
}.start();
}
}
class MySynchronized {
public static synchronized void print(String str) {
System.out.println("線程: " + Thread.currentThread().getName() + "開始執行");
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "打印了信息:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("線程: " + Thread.currentThread().getName() + "執行結束");
}
}
//代碼運行結果:
線程: 線程A開始執行
線程A打印了信息:0
線程A打印了信息:1
線程A打印了信息:2
線程A打印了信息:3
線程A打印了信息:4
線程A打印了信息:5
線程A打印了信息:6
線程A打印了信息:7
線程A打印了信息:8
線程A打印了信息:9
線程: 線程A執行結束
線程: 線程B開始執行
線程B打印了信息:0
線程B打印了信息:1
線程B打印了信息:2
線程B打印了信息:3
線程B打印了信息:4
線程B打印了信息:5
線程B打印了信息:6
線程B打印了信息:7
線程B打印了信息:8
線程B打印了信息:9
線程: 線程B執行結束
synchronized 對象鎖 示例代碼 (單純用synchronized修飾代碼塊,)
3.ReentranLock類有什麼作用?它常用的方法有哪幾個?分別有什麼特點?
4.集群環境下多機器間進行同步操作有什麼可選的解決方案?(最好用偽代碼寫出關鍵部分)
5.列出樂觀鎖的設計要點和使用方法?
6.何為冪等性控制?舉一個例子說明你之前如何實現冪等性控制?(或在項目IDCM中如何實現冪等性控制?)
7.spring實現aop用到的關鍵技術是什麼?
8.HashMap和ConcurrentHashMap有什麼區別和特點?
9.java.util.concurrent package下,你用過哪些類?分別有什麼用途和特點?
10.如果一張表數據量較大,影響了查詢性能,可以有哪些優化方案?建立索引有什麼原則?
11.說一說數據庫事務隔離級別的理解?(項目IDCM中是如何使用的?)
12.Spring中注解@Component @Repository @Service @Controller的區別?(項目IDCM中context:component-scan注解掃描是如何配置的?)