常常看到一些類,有的說線程安全,有的說線程不安全,頓時懵逼。java
線程安全不安全,主要是在多線程執行的狀況下,若是因爲線程之間搶佔資源而形成程序的bug即爲線程不安全,下面就拿arraylist 和Vector來舉個例子:安全
這裏的arraylist 是線程不安全的,Vector是線程安全的多線程
package Thread; import java.util.List; import java.util.concurrent.CountDownLatch; public class MyThread implements Runnable{ private List<Object> list; private CountDownLatch countDownLatch; public MyThread(){} public MyThread(List<Object> list,CountDownLatch countDownLatch){ this.list=list; this.countDownLatch=countDownLatch; } @Override public void run() { //給每一個線程添加10個元素 for(int i=0;i<10;i++){ list.add(new Object()); } //完成一個子線程 countDownLatch.countDown(); } }
package Thread; import java.util.ArrayList; import java.util.List; import java.util.Vector; import java.util.concurrent.CountDownLatch; public class ThreadTest { /** * 這裏要比較的是arraylist 和Vector來測試 * arraylist 是線程不安全的 * Vector 線程安全的 * */ public static void test(){ //用來測試的list集合 List<Object> list= new ArrayList<Object>(); //List<Object> list = new Vector<Object>(); //線程數 int threadCount =10000; //用來讓主線等待thread 個執行完畢 CountDownLatch count=new CountDownLatch(threadCount); for(int i=0;i<threadCount;i++){ Thread thread=new Thread(new MyThread(list, count)); thread.start(); } try { //主線程全部都執行完成後,再向下執行 count.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(list.size()); } public static void main(String[] args) { for(int i=0;i<10;i++){ test(); } } }
運行結構:ide
99995
99998
99989
99973
99894
99970
99974
99977
99990
99989測試
當使用Vector時,即把測試的集合換一下this
package Thread; import java.util.ArrayList; import java.util.List; import java.util.Vector; import java.util.concurrent.CountDownLatch; public class ThreadTest { /** * 這裏要比較的是arraylist 和Vector來測試 * arraylist 是線程不安全的 * Vector 線程安全的 * */ public static void test(){ //用來測試的list集合 //List<Object> list= new ArrayList<Object>(); List<Object> list = new Vector<Object>(); //線程數 int threadCount =10000; //用來讓主線等待thread 個執行完畢 CountDownLatch count=new CountDownLatch(threadCount); for(int i=0;i<threadCount;i++){ Thread thread=new Thread(new MyThread(list, count)); thread.start(); } try { //主線程全部都執行完成後,再向下執行 count.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(list.size()); } public static void main(String[] args) { for(int i=0;i<10;i++){ test(); } } }
這樣運行的結果:線程
100000
100000
100000
100000
100000
100000
100000
100000
100000
100000blog
很明顯,使用Vector 這個類運行正確,這就是所謂的線程安全資源
固然,這只是代碼層面上的,其實多線程不安全,主要由於cpu分配機制,誰得到了cpu誰就能執行,所以形成了線程的不安全.同步
咱們能夠使用synchronized 關鍵字來同步代碼塊,達到線程安全:
下面舉個synchronized同步的例子:
package Thread1; public class Bank { private int sum = 0; public void add(int n) { sum = sum + n; System.out.println("sum= " + sum); } } package Thread1; public class Cus implements Runnable { Bank b = new Bank(); @Override public void run() { for (int i = 0; i < 3; i++) { b.add(100); } } } package Thread1; public class Test { public static void main(String[] args) { Cus c = new Cus(); for (int i = 0; i < 3; i++) { new Thread(c).start(); } } }
沒有使用synchronized修飾的時候,運行結構是:
sum= 100
sum= 400
sum= 500
sum= 300
sum= 200
sum= 600
sum= 800
sum= 700
sum= 900
固然synchronized 必需要在線程運行的代碼塊中修飾:
package Thread1; public class Bank { private int sum = 0; public void add(int n) { sum = sum + n; System.out.println("sum= " + sum); } } package Thread1; public class Cus implements Runnable { Bank b = new Bank(); @Override public void run() { synchronized(this){ for (int i = 0; i < 3; i++) { b.add(100); } } } } package Thread1; public class Test { public static void main (String [] args) { Cus c = new Cus(); for(int i=0;i<3;i++){ new Thread(c).start(); } } }
這樣保證,每次只有一個線程在運行,結果爲:
sum= 100
sum= 200
sum= 300
sum= 400
sum= 500
sum= 600
sum= 700
sum= 800
sum= 900
OK,OVER
天天進步一點點,堅持下去