Home > front end >  How can we ensure that instances of this class can be safely used by multiple threads?
How can we ensure that instances of this class can be safely used by multiple threads?

Time:01-18

This class is intended to allow users to write a series of messages, so that each message is identified with a timestamp and the name of the thread that wrote the message

public class Logger {
    private StringBuilder contents = new StringBuilder();

    public void log(String message) {
        contents.append(System.currentTimeMillis());
        contents.append(": ");
        contents.append(Thread.currentThread().getName());
        contents.append(message);
        contents.append("\n");
    }

    public String getContents() {
        return contents.toString();
    }
}

CodePudding user response:

If you really intend to collect logs like this, the most simple approach would be to use a synchronized section to make sure that only one thread at a time can access the contents field:

public class Logger {

    private final StringBuilder contents = new StringBuilder();

    public void log(String message) {
        synchronized (contents) {
            contents.append(System.currentTimeMillis());
            contents.append('[');
            contents.append(Thread.currentThread().getName());
            contents.append("]: ");
            contents.append(message);
            contents.append("\n");
        }
    }

    public String getContents() {
        synchronized (contents) {
            return contents.toString();
        }
    }
}

The field should be final in order to safely serve as a lock.

More about synchronized: https://www.baeldung.com/java-synchronized#the-synchronized-keyword

CodePudding user response:

You can constrain exclusive access to a Logger object by simply adding the synchronized keyword to each method.

public class Logger {

    private StringBuilder contents = new StringBuilder();

    public synchronized void log(String message) {
        contents.append(System.currentTimeMillis());
        contents.append('[');
        contents.append(Thread.currentThread().getName());
        contents.append("]: ");
        contents.append(message);
        contents.append("\n");
    }

    public synchronized String getContents() {
        return contents.toString();
    }
}

This is equivalent to

public class Logger {

    private final StringBuilder contents = new StringBuilder();

    public void log(String message) {
        synchronized (this) {
            contents.append(System.currentTimeMillis());
            contents.append('[');
            contents.append(Thread.currentThread().getName());
            contents.append("]: ");
            contents.append(message);
            contents.append("\n");
        }
    }

    public String getContents() {
        synchronized (this) {
            return contents.toString();
        }
    }
}
  • Related