使用多線程,最重要的就是安全問題,何為安全問題?
public class ThreadTest1 { public static void main(String[] args) { MyRunnable runnable = new MyRunnable(); new Thread(runnable).start(); new Thread(runnable).start(); new Thread(runnable).start(); new Thread(runnable).start(); } }class MyRunnable implements Runnable{ PRivate int i = 100; public void run() { while(true){ if(i > 0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i--); } } }}執行結果:....876543210-1-2可以看出,執行結果出了問題,出現了0,-1,-2等非法數據,這是因為:
這就是使用多線程產生的安全問題。
產生的原因是:
多線程操作共享數據。
解決方法:對操作共享數據的代碼片段進行同步。使用關鍵字synchronized.
第一:同步代碼塊
語法:
synchronized(對象){
//要同步的代碼塊
}
synchronzied上鎖必須有個對象,同一個對象鎖才能保證上鎖是對多個線程之間有作用的。
對上述有安全問題的代碼進行改造:
class MyRunnable implements Runnable{ private int i = 100; public void run() { while(true){ synchronized(this){ //這個this代表當前對象,這里換成其他對象也可以的。 if(i > 0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i--); } } } }}這樣就不會出問題了。第二種:同步方法
語法: public synchronized void add().。用synchronized關鍵字對方法進行修飾,那么此方法就成為了同步方法。
class MyRunnable implements Runnable{ private int i = 100; public void run() { while(true){ cutDown(); } } public synchronized void cutDown(){ if(i>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i--); } }}值得注意的是,我們說了,synchronzied需要一個對象鎖,而對方法上鎖并沒有看到這個鎖在哪里,其實對方法上鎖默認為this鎖。第三種:對靜態方法上鎖
public static synchronized void cutDown(){ if(i>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i--); } }靜態方法的鎖,是他所在類的class對象,比如說上述實例,他的鎖就是MyRunnable.class對象,如果有靜態代碼塊需要和他同步,那么synchronized(類.class){}來同步,否則不起作用。
新聞熱點
疑難解答