@Igor-Novikov

Как работать со StringBuffer в многопотоке?

Здравствуйте. Столкнулся с проблемой неправильно работы потоков при записи значения в StringBuffer. Иногда они накладываются друг на друга и записывают неверное значение.

Есть форма ввода, на которую установлен слушатель ввода. При добавлении или удалении нового символа он срабатывает, создавая объект класса Translate и выполняет метод beginTranslate.

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


Создается объект класса и выполняется метод, который создает новый поток обращения к API переводчикa Google.
Результат помещается в StringBuffer outputText и выводится на экран. При быстром вводе фразы в поле ввода происходит наложение потоков и в форму вывода выходит неправильный перевод. Почему так происходит? Ведь StringBuffer синхронизированный по умолчанию, так я еще добавил синхронизированный блок в метод run.

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();
                    }
            }
        }
  • Вопрос задан
  • 145 просмотров
Пригласить эксперта
Ответы на вопрос 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Java
Седой и строгий
StringBuffer давно устарел и не рекомендуется к применению. О чём можно найти упоминания в "Effective Java" Джошуа Блоха, "Java Concurrency in Practice" Брайана Гетца и многих других учебниках. Его основное отличие от StringBuilder в том, что вызов метода append синхронизирован. В однопоточной среде это приводит к бесполезному замедлению программы. А в многопоточной бесполезно, так как смысл имеет только совместная синхронизация всех вызовов append, а не каждого по отдельности.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы