Home > database >  Why String Builder is returning its length zero, while returning some value of it
Why String Builder is returning its length zero, while returning some value of it

Time:02-01

In below program, String buffer is working as expected, but in case of string builder, the length of String builder is zero, while it's giving me some data. So my question is, if string builder has some value, how can it return its length zero?

public class SbVsSbf2 {

    static StringBuilder sb = new StringBuilder();
    static StringBuffer sbf = new StringBuffer();

    public static void main(String[] args) throws InterruptedException {
        // Thread 1
        Thread t1 = new Thread(() -> {
            for (int i = 0; i <= 23; i  ) {
                sb.append(i);
                sbf.append(i);
            }
        });

        // Thread 2
        Thread t2 = new Thread(() -> {
            for (int i = 0; i <= 23; i  ) {
                sb.append(i);
                sbf.append(i);
            }
        });

        t1.start();
        t2.start();

        System.out.println("StringBuilder: "   sb.length());
        System.out.println("StringBuffer: "   sbf.length());
        System.out.println("StringBuilder: "   sb);
        System.out.println("StringBuffer : "   sbf);

    }
}

CodePudding user response:

This is mainly a matter of timing. You can replace StringBuilder with StringBuffer and get a similar result.

For example, when I run the following program on my machine

public class ThreadStart {
  static StringBuilder sb = new StringBuilder();

  static long firstAction;

  public static void main(String[] args) throws InterruptedException {
    
      Thread t1 = new Thread(() -> firstAction = System.nanoTime());
      long starting = System.nanoTime();
      t1.start();
      int length = sb.length();
      long afterReadingLength = System.nanoTime();
      String s = "StringBuilder: "   length;
      long afterConcatenation = System.nanoTime();
      System.out.println(s);
      long andPrintln = System.nanoTime();
      t1.join();

      System.out.printf("time until %-20s %,d ns%n",
                        "thread's 1st action", firstAction - starting);
      System.out.printf("time until %-20s %,d ns%n",
                        "reading sb.length()", afterReadingLength - starting);
      System.out.printf("time until %-20s %,d ns%n",
                        "string concatenation", afterConcatenation - starting);
      System.out.printf("time until %-20s %,d ns%n",
                        "println completion", andPrintln - starting);
  }
}

I get results similar to

StringBuilder: 0
time until thread's 1st action  399.000 ns
time until reading sb.length()  181.300 ns
time until string concatenation 195.300 ns
time until println completion   392.800 ns

though numbers can vary significantly between runs. It demonstrates the order of magnitude of the operations involved.

Starting a thread takes a significant amount of time. That’s one of the reasons why we use thread pools; handing a task over to an already running worker thread is significantly faster than starting a new thread.

Some of the work has been done within the start() method execution in the main thread. I did not try to separate it from the execution of sb.length() here, as the time measurement wouldn’t be precise enough. It’s clearly visible that the background thread is far away from doing anything by the time, sb.length() returned. Even the string concatenation is not expensive enough.

But after the execution of the first println call, we get into the same order of magnitude, so overlapping of the background thread’s activity with the main thread may happen after that.


It’s still important to emphasize that you must not rely on any assumed timing and changing an object from multiple threads can give you unpredictable results.

CodePudding user response:

The length of a StringBuilder object is determined by its length property, which represents the number of characters currently in the sequence. The length property is updated each time a character is added to or removed from the sb object.

In your code, two threads are concurrently modifying the same sb object, which can cause some unexpected results. In a multi-threaded environment, sb is not thread-safe and should not be used for concurrent modifications. On the other hand, sb is thread-safe and can be used for concurrent modifications, which is why you are seeing the expected results in this case.

  • Related