VanillaChronicle的线程安全性

时间:2014-05-12 18:48:42

标签: java chronicle

我正在使用VanillaChronicle将一些消息写入磁盘。

public final class ConcurrentPersister{

    private final String location;
    private final Chronicle chronicle;
    private final ExcerptAppender writer;

    private final static int STRING_SIZE_OVERHEAD   = 1000;
    private final static String FILE_DATE_FORMAT    = "MM-dd-yyyy";
    private final static String NAME                = "ConcurrentPersister";
    private final static Logger LOGGER              = LoggerFactory.getLogger( NAME );



    public ConcurrentPersister( String location, VanillaChronicleConfig config ){
        this.chronicle      = new VanillaChronicle( location );
        this.writer         = chronicle.createAppender();
    }


   public final void appendMessage( final String message ){

        try{

            long length  =  STRING_SIZE_OVERHEAD + message.length();

            writer.startExcerpt( length );
            writer.append( message );
            writer.finish();

        }catch( Exception e ){
            LOGGER.warn("Failed to persist Message [{}]", message );
            LOGGER.warn("Exception: ", e );
        }

    }

}

如上所示,appendMessage(String message)方法是否是从多个线程调用的线程安全的?

我在某地读过VanillaChronicle的追加(字符串消息)是线程安全的。 但是,我认为startExcerpt()+ append()+ finish()的复合动作不是线程安全的吗?

感谢。

2 个答案:

答案 0 :(得分:3)

VanillaChronicle有一个appenders / tailers的ThreadLocal缓存:

public VanillaAppender createAppender() throws IOException {
    WeakReference<VanillaAppender> ref = appenderCache.get();
    VanillaAppender appender = null;
    if (ref != null)
        appender = ref.get();
    if (appender == null) {
        appender = createAppender0();
        appenderCache.set(new WeakReference<VanillaAppender>(appender));
    }
    return appender;
}

如果你没有数千个短生命线程,你可以在appendMessage方法中使用createAppender

public final void appendMessage( final String message ) {
    try {
        ExcerptAppender writer = chronicle.createAppender();
        writer.startExcerpt( STRING_SIZE_OVERHEAD + message.length() );
        writer.append( message );
        writer.finish();
    } catch( Exception e ) {
        LOGGER.warn("Failed to persist Message [{}]", message );
        LOGGER.warn("Exception: ", e );
    }
}
  

我在某地读过VanillaChronicle的append(String message)是线程安全的。但是,我是否认为startExcerpt() + append() + finish()的复合行为不是线程安全的?

VanillaChronicle可以由并发线程使用,即使是并发进程,只要每个线程使用它自己的appender。

答案 1 :(得分:0)

您需要在这三个方法调用上同步编写器。 append( message );可能是线程安全的,但正如你所说,如果多个线程通过同一个ConcurrentPersister实例访问该方法,那么对writer的三个单独方法调用可能会发生冲突。

public final class ConcurrentPersister{

    private final String location;
    private final Chronicle chronicle;
    private final ExcerptAppender writer;

    private final static int STRING_SIZE_OVERHEAD   = 1000;
    private final static String FILE_DATE_FORMAT    = "MM-dd-yyyy";
    private final static String NAME                = "ConcurrentPersister";
    private final static Logger LOGGER              = LoggerFactory.getLogger( NAME );



    public ConcurrentPersister( String location, VanillaChronicleConfig config ){
        this.chronicle      = new VanillaChronicle( location );
        this.writer         = chronicle.createAppender();
    }


   public final void appendMessage( final String message ){

        try{

            long length  =  STRING_SIZE_OVERHEAD + message.length();

            synchronized(writer){
                writer.startExcerpt( length );
                writer.append( message );
                writer.finish();
               }

        }catch( Exception e ){
            LOGGER.warn("Failed to persist Message [{}]", message );
            LOGGER.warn("Exception: ", e );
        }

    }

}

根据您对此类的其他操作,可能更容易同步整个方法。

   public synchronized final void appendMessage( final String message ){

但这会在ConcurrentPersister的实例上同步,而不是编写器。