如何从超类中确保子类'方法的线程安全?

时间:2018-05-26 17:55:47

标签: java inheritance synchronization

我参加了面试,并被要求为以下要求设计课程。 假设我有一个A类,它可以有任意数量的子节点,即子类。 A类有一个名为doS​​omething()的方法,它是同步的。要求是:

  1. A 的所有子类都必须覆盖doSomething()方法。
  2. 所有子类'覆盖doSomething()方法本质上必须是线程安全的
  3. 所有子类'必须具有条款才能为其doSomething()方法实现实现自己的逻辑
  4. A类的构造函数由我决定(设计师)来决定如何实现。

    设计人员无法控制将创建多少个子类或如何创建它们,即设计人员只能为超类编写代码

  5. 我建议将类抽象化,并将doSomething()方法抽象化。这意味着扩展我的类的类必然会提供自己的doSomething()方法。

    但是,我无法回答我的班级A究竟在哪些方面确保了我的子课程的线程安全,而且对于doSomething()方法也是如此。

    他给了一个提示,他说这个诀窍是在A类的构造函数中完成的。

    有什么想法吗?

2 个答案:

答案 0 :(得分:1)

经过长时间的研究后,我发现,如果重写该方法并且未在重写方法的签名中明确添加关键字synchronization,则无法继承synchronized

因为这个问题主要是为了防止其他用户(即开发人员)违反使用你的类(因为他们正在扩展它)。

我想出了一种利用Java中Reflection类来解决它的方法。

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class A {
    public A(){
         assertSynch("doSomething");
    }

    // method to assert a particular method is synchronized in the subclass
    private void assertSynch(String methodName) {
        Class<? extends A> subclass = this.getClass(); // this returns the subclass
        Method[] methods = subclass.getDeclaredMethods();
        for (Method meth : methods) { // loop through the methods in subclass
            if(meth.getName().equals(methodName)) { // when it reaches your method
                String modVal = Modifier.toString(meth.getModifiers()); // get its modifier
                if(!modVal.contains("synchronized")) { // check if it contains the keyword "synchronized"
                    try { // if not -> throw an Exception with clear message about the reason and exit
                        throw new Exception(methodName + 
                             " must be synchronized to ensure class thread safety!");
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(0);
                    }
                }
            }
         }
    }

    public synchronized void doSomething() {} 
}
public class B extends A{
    public B() { } // it implicitly calls the superclass constructor

    @Override
    public void doSomething() { } // it will make the program to throw the above exception
}

答案 1 :(得分:1)

我会说更好地制作basedoSomething方法public final synchronizedfinal以确保子类不能覆盖它)并调用另一个protected abstract } 方法。 public synchronized final void doSmoething确保any calldoSomething方法为synchronized / thread safedoSmoethingImpl抽象方法可以灵活地在子类中赋予方法自己的定义。

abstract class A {
    public synchronized final void doSmoething() {
        doSmoethingImpl();
    }
    protected abstract void doSmoethingImpl();


}

class B extends A {
    @Override
    protected void doSmoethingImpl() {
        // definition in class B
    }
}

注意:上述解决方案不会直接满足您的要点1,但doSmoethingImpl()将为您提供间接实现类似功能的范围。