有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在Java中,多线程是作为线程安全的方法参数的方法引用

我有以下情况:

interface ValueBinding<T> {
    public void setValue(T input);
}

public enum FacesBinding {
    VALUE;
    public void bindString(ValueBinding<String> fcn, HttpServletRequest req, String param){
        try {
            String val = req.getParameter(param);
            if( val != null )
                fcn.setValue(val);
        } catch (Exception e) { }        
    }
    public void bindBoolean(ValueBinding<Boolean> fcn, HttpServletRequest req, String param){
        try {
            fcn.setValue(req.getParameter(param) != null);
        } catch (Exception e) { }        
    }
    public void bindInt(ValueBinding<Integer> fcn, HttpServletRequest req, String param){
        try {
            int val = Integer.parseInt(req.getParameter(param));
            fcn.setValue(val);
        } catch (Exception e) { }        
    }
    public void bindLong(ValueBinding<Long> fcn, HttpServletRequest req, String param){
        try {
            long val = Long.parseLong(req.getParameter(param));
            fcn.setValue(val);
        } catch (Exception e) { }        
    }
...
...
}

我在这样的“多线程”环境中使用它:

并发线程正在调用此方法

            @Override // concurrent Threads are calling this method
            public Category initData(FacesContext facesContext) throws Exception {
                Category entity = new Category();
                HttpServletRequest req = facesContext.getRequest();
                FacesBinding.VALUE.bindLong(entity::setId, req, Table.Category.Field.ID.name());
                FacesBinding.VALUE.bindString(entity::setName, req, Table.Category.Field.NAME.name());

                FacesBinding.VALUE.bindInt(entity::setPosition, req, Table.Category.Field.POSITION.name());
                FacesBinding.VALUE.bindBoolean(entity::setLocalized, req, Table.Category.Field.LOCALIZED.name());           
                return entity;
            }

是吗

FacesBinding.VALUE.bindLong(entity::setId, req, Table.Category.Field.ID.name());

100%线程安全当我将方法引用(接口)entity::setId作为枚举对象(单例)中方法的参数传递时

注:

entity::setId

entity::setName

entity::setPosition

。。。所有这些方法都是标准的java setter方法

public void setId(long id) {
        this.id = id;
    }
public void setName(String name) {
        this.name = name;
    }
....

更新:

具体来说:

Category entity = new Category();
entity.setId(5);//thread safe for sure

100%等于

FacesBinding.VALUE.bindLong(entity::setId, ...);

FacesBinding是单例,而bindLong(entity::setId, ...)中的方法引用,这一事实是否会导致线程不安全


共 (1) 个答案

  1. # 1 楼答案

    如果setId方法是线程安全的,那么方法引用调用将是线程安全的

    方法引用是创建ValueBinding对象的一种别致的简写方式。编译它们时,将有一个私有的内部排序类,它实现函数接口并调用指定的方法。由于您指定了属于某个对象的方法,这个内部类也将等效于具有接受Category对象的构造函数,以及存储它的私有字段(我说的等效于,因为默认情况下,如果可以证明并选择任何其他实现,则实现不限于此行为)