I
I
Igor-Novikov2019-11-12 22:50:12
Java
Igor-Novikov, 2019-11-12 22:50:12

How to work with StringBuffer in multithread?

Hello. I ran into a problem with threads not working correctly when writing a value to a StringBuffer. Sometimes they overlap and write the wrong value.
I have an input form that has an input listener. When a new character is added or removed, it fires by creating an object of the Translate class and executing the beginTranslate method.

Translate translate = new Translate();
translate.beginTranslate();

A class object is created and a method is executed that creates a new call flow to the Google Translator API.
The result is placed in a StringBuffer outputText and displayed on the screen. When you quickly enter a phrase in the input field, there is an overlay of flows and an incorrect translation appears in the output form. Why is this happening? After all, StringBuffer is synchronized by default, so I also added a synchronized block to the run method.
class Translate {
        //запись введеного текста в inputText
        public synchronized void beginTranslate() {
            inputText.delete(0, inputText.length());
            Document leftFieldDocument = leftField.getDocument();
            try {
                inputText.append(leftFieldDocument.getText(0, leftFieldDocument.getLength()));
            } catch (BadLocationException ex) {
                Logger.getLogger(MainForm.class.getName()).log(Level.SEVERE, null, ex);
            }

            if (inputText.toString() != "") {
                Translate.GoogleTranslateAPIThread googleTranslateThread = new Translate().new GoogleTranslateAPIThread();
                googleTranslateThread.start();
            }
        }

        class GoogleTranslateAPIThread extends Thread {
                   
            @Override
            public void run() {
                    synchronized(this){
                    GoogleTranslateAPI googleTranslateOutput = new GoogleTranslateAPI(inputText.toString(), inputLanguage.toString(), outputLanguage.toString());
                    outputText.delete(0, outputText.length());
                    outputText.append(googleTranslateOutput.getGoogleTranslate());
                    rightField.setText(outputText.toString());
                    rightField.validate();
                    }
            }
        }

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Gornostaev, 2019-11-13
@sergey-gornostaev

StringBuffer is deprecated and deprecated. What can be found in "Effective Java" by Joshua Bloch, "Java Concurrency in Practice" by Brian Goetz and many other textbooks. Its main difference from StringBuilder is that the call to the append method is synchronized. In a single-threaded environment, this leads to useless slowdown of the program. But in multi-threaded it is useless, since only joint synchronization of all append calls, and not each one separately, makes sense.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question