在Java中,如何在TextArea中使用多线程?我需要同步我的线程吗?

时间:2019-11-20 06:28:50

标签: java multithreading synchronization

我对Java和多线程没有经验,所以也许你们可以帮忙。多线程时,在TextArea框中打印一系列数字和字母时遇到问题。这是我的代码:

public class MultiThread extends Application {
    static TextArea outputArea = new TextArea();
@Override
    public void start(Stage primaryStage) throws Exception {

        outputArea.setWrapText(true);
        Runnable printA = new PrintChar('a', 100);
        Runnable printB = new PrintChar('b', 100);
        Runnable print100 = new PrintNum(100);

        // Create threads
        Thread thread1 = new Thread(printA);
        Thread thread2 = new Thread(printB);
        Thread thread3 = new Thread(print100);

        thread1.start();
        thread2.start();
        thread3.start();

        Scene scene = new Scene(outputArea, 250, 130);
        primaryStage.setTitle("Concurrent Output");
        primaryStage.setScene(scene);
        primaryStage.show();}


    public static void main(String[] args) {
        launch(args);
    }
}
class PrintChar extends MultiThread implements Runnable {
    private char charToPrint; // The character to print
    private int times; // The times to repeat

    public PrintChar(char c, int t) {
        charToPrint = c;
        times = t;
    }

    @Override
    public void run() {
        for (int i = 0; i < times; i++) {
            outputArea.appendText(charToPrint + "");
        }
    }
}

class PrintNum extends MultiThread implements Runnable {
    private int lastNum;
    private char charToPrint;

    public PrintNum(int n) {
        lastNum = n;
    }

    @Override
    public void run() {
        for (int i = 1; i <= lastNum; i++) {
            outputArea.appendText(i + "");
        }
    }
}

当我运行代码时,线程通常不会打印出它们应有的全部内容。例如,“ print100”并不总是像预期的那样打印到100号。我也会得到随机结果,而每次都不会得到相同的输出也不会出错。

Exception in thread "Thread-6" Exception in thread "Thread-4" java.lang.IndexOutOfBoundsException
    at javafx.scene.control.TextInputControl.getText(TextInputControl.java:451)
    at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:564)
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548)
    at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:473)
    at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:463)
    at threader.PrintChar.run(Threader.java:53)
    at java.lang.Thread.run(Thread.java:748)
java.lang.IndexOutOfBoundsException
    at javafx.scene.control.TextInputControl.getText(TextInputControl.java:451)
    at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:555)
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548)
    at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:473)
    at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:463)
    at threader.PrintNum.run(Threader.java:71)
    at java.lang.Thread.run(Thread.java:748)

我几乎可以肯定的是,同步代码中的多个线程是一个问题,但是我似乎无法弄清楚该特定代码如何实现。

2 个答案:

答案 0 :(得分:1)

#include <bcm2835.h> #include <stdio.h> // PWM output on RPi Plug P1 pin 12 (which is GPIO pin 18) // in alt fun 5. // Note that this is the _only_ PWM pin available on the RPi IO headers #define PIN RPI_GPIO_P1_12 // and it is controlled by PWM channel 0 #define PWM_CHANNEL 0 // This controls the max range of the PWM signal #define RANGE 1024 int main(int argc, char **argv) { if (!bcm2835_init()) return 1; // Set the output pin to Alt Fun 5, to allow PWM channel 0 to be output there bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_ALT5); // Clock divider is set to 16. // With a divider of 16 and a RANGE of 1024, in MARKSPACE mode, // the pulse repetition frequency will be // 1.2MHz/1024 = 1171.875Hz, suitable for driving a DC motor with PWM bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_16); bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1); //CTL reg bcm2835_pwm_set_range(PWM_CHANNEL, RANGE); //RNG1/2 reg // Vary the PWM m/s ratio between 1/RANGE and (RANGE-1)/RANGE int direction = 1; int data = 1; while (1) { if (data == 1) direction = 1; else if (data == RANGE-1) direction = -1; data += direction; bcm2835_pwm_set_data(PWM_CHANNEL, data); bcm2835_delay(1); } bcm2835_close(); return 0; } 实现显然不是线程安全的,因此在调用 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxx"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:allowBackup="false" android:theme="@style/AppTheme" android:hardwareAccelerated="true" android:largeHeap="true" android:usesCleartextTraffic="true" > <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".NotifierActivity" android:label="SOS" android:icon="@mipmap/ic_launcher_sos" android:roundIcon="@mipmap/ic_launcher_sos_round" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 对象上的方法时,应确保当前线程没有中断。例如,您可以通过同步TextArea对象本身来做到这一点:

TextArea

答案 1 :(得分:1)

MultiThread类中创建静态函数,如下所示:

public static synchronized setText(String str) {
     outputArea.appendText(str);
}

,并将行outputArea.appendText(...);替换为MultiThread.setText(...)

问题:您当前正在通过三个线程在outputArea上设置文本,并且它们一次都试图将文本添加到outputArea上。因此,outputArea中用于附加文本的索引与另一个线程重叠。

解决方案:确保只有一个线程尝试在outputArea上追加文本。