Vector 執行緒安全與不安全
阿新 • • 發佈:2019-01-10
下面這樣寫法是執行緒不安全的寫法
import java.util.Vector; public class Test { private static Vector<Integer> vector = new Vector<Integer>(); public static void main(String[] args) { while (true) { for (int i = 0; i < 10; i++) { System.out.println("新增"); vector.add(i); } Thread removeThread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < vector.size(); i++) { System.out.println("removeThread刪除"); vector.remove(i); } } }); Thread printThread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < vector.size(); i++) { System.out.println("printThread獲取"); System.out.println((vector.get(i))); } } }); removeThread.start(); printThread.start(); //不要同時產生過多的執行緒,否則會導致作業系統假死 while (Thread.activeCount() > 20); } } }
儘管Vector get()、remove()、get() 方法是I同步的 但執行上面程式會出現以下錯誤
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0 at java.util.Vector.get(Vector.java:744) at Test$2.run(Test.java:29) at java.lang.Thread.run(Thread.java:722) Exception in thread "Thread-14857" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0 at java.util.Vector.get(Vector.java:744) at Test$2.run(Test.java:29) at java.lang.Thread.run(Thread.java:722)
會出現很多null值,但不錯,因為沒有那個key ,但不會報錯import java.util.Hashtable; import java.util.Map; public class HashmapTest { private static Map<Integer,Integer> hashtable= new Hashtable<Integer,Integer>(); public static void main(String[] args) { while(true){ for (int i = 0; i < 10; i++) { System.out.println("新增"); hashtable.put(i, i); } Thread removeThread = new Thread(new Runnable() { @Override public void run() { Iterator it = hashtable.entrySet().iterator(); while (it.hasNext()) { Map.Entry<integer integer=""> entry=(Entry<integer integer="">) it.next(); System.out.println("delete this: "+entry.getKey()+"==="+entry.getValue()); it.remove(); } } Thread getThread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < hashtable.size(); i++) { System.out.println("getThread獲取"); System.out.println((hashtable.get(i))); } } }); removeThread.start(); getThread.start(); while (Thread.activeCount() > 20); } } } </integer></integer>
getThread獲取
null
getThread獲取
null
在多執行緒環境中,如果不在方法呼叫端做額外的同步措施,使用這段仍是執行緒不安全的,因為如果一個執行緒恰好再錯誤的時間刪除了一個元素, 導致i不在可用的話,get方法會丟擲一個ArrayIndexOutOfBoundsException
import java.util.Vector;
public class Test {
private static Vector<Integer> vector = new Vector<Integer>();
public static void main(String[] args) {
while (true) {
for (int i = 0; i < 10; i++) {
System.out.println("新增");
vector.add(i);
}
Thread removeThread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (vector) {
for (int i = 0; i < vector.size(); i++) {
System.out.println("removeThread刪除");
vector.remove(i);
}
}
}
});
Thread printThread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (vector) {
for (int i = 0; i < vector.size(); i++) {
System.out.println("printThread獲取");
System.out.println((vector.get(i)));
}
}
}
});
removeThread.start();
printThread.start();
//不要同時產生過多的執行緒,否則會導致作業系統假死
while (Thread.activeCount() > 20);
}
}
}