线程安全-005-synchronized其他概念

一、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();
    }
}

 二、父子类

有父类、子类继承关系的,父类和子类都加上synchronized关键字,也是线程安全的,可以放心去用。

例子程序:

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();
    }

}

打印结果;

 三、出现异常,锁自动释放

例子程序:

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();
        
    }
}

打印结果;

如果整个任务是一个整体,1,可以 catch InterruptedException

运行结果:

2,中断线程的执行,也可以在catch里抛出运行时异常:

执行结果:

猜你喜欢

转载自www.cnblogs.com/lihaoyang/p/10542230.html