線程安全-005-synchronized其餘概念

1、Synchornized鎖重入

例子程序:安全

package com.lhy.thread01;

public class SyncDouble1 {

    public synchronized void method1(){
        System.err.println("method-1....");
        method2();
    }
    public synchronized void method2(){
        System.err.println("method-2....");
        method3();
    }
    public synchronized void method3(){
        System.err.println("method-3....");
    }
    
    public static void main(String[] args) {
        final SyncDouble1 sd = new SyncDouble1();
        Thread t1 = new Thread(new Runnable(){
            @Override
            public void run() {
                sd.method1();
            }
        });
        t1.start();
    }
}

 2、父子類

有父類、子類繼承關係的,父類和子類都加上synchronized關鍵字,也是線程安全的,能夠放心去用。ide

例子程序:this

package com.lhy.thread02;

public class SyncDouble2 {
    
    static class Main{
        public  int i=10;
        public synchronized void operationSup(){
            try {
                i--;
                System.err.println("Main print i ="+i);
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    static class Sub extends Main{
        public synchronized void operationSub(){
            try {
                while(i > 0){
                    i--;
                    System.err.println("Sub print i = "+i);
                    Thread.sleep(100);
                    this.operationSup();//調用父類的方法
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                Sub sub = new Sub();
                sub.operationSub();
            }
        });
        t1.start();
    }

}

 

打印結果;spa

 3、出現異常,鎖自動釋放

例子程序:線程

package com.lhy.thread02;

/**
 * 模擬synchronized加鎖的方法,發生異常時,怎麼處理
 * @author dev
 *
 */
public class SyncException {

    private int i = 0;
    boolean flag = true;
    
    //傳過來多個任務,taskSize模擬任務個數
    public synchronized void operation(int taskSize){
        
        while(flag){
            try {
                i++;
                Thread.sleep(200);
                System.err.println(Thread.currentThread().getName()+" ,i =" +i);
                if(i == (taskSize/2)){//模擬任務執行了一半
                    Integer.parseInt("a"); //發生異常
                    //throw new RuntimeException();
                }
                //任務執行完了中止
                if(i == taskSize){
                    shutdown();
                }
            } catch (Exception e) { //catch到InterruptedException,再也不往下執行
                e.printStackTrace();
                //狀況一:全部任務不是一個總體,一個有問題不影響其餘,只把出錯的記錄日誌,下次執行,此時catch應該捕捉Exception。/continue;
                System.err.println("這裏能夠記錄到日誌,i=  "+i);
                //狀況二:全部任務是一個總體,一個有問題影響其餘,此時能夠經過捕捉InterruptedException、catch裏拋出RuntimeException();來終止線程繼續執行
                //throw new RuntimeException();
                //continue;
            }
        }
    }
    //終止
    public void shutdown(){
        this.flag = false;
    }
    
    public static void main(String[] args) {
        final SyncException se = new SyncException();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                se.operation(10);
            }
        },"t1");
        t1.start();
        
    }
}

打印結果;3d

 

若是整個任務是一個總體,1,能夠 catch InterruptedException日誌

運行結果:code

2,中斷線程的執行,也能夠在catch裏拋出運行時異常:blog

執行結果:繼承

相關文章
相關標籤/搜索