title: I am running a javafx program and I am getting an IllegalStateException in a situation where I would expect usual Thread interference
body: <p>tl:dr at the bottom. I am taking a Java course on Udemy and our instructor is demonstrating a situation where background threads can interfere with each other and crash the program. In this case pushing either of the two buttons initiates a method that starts a background Thread, waits, then updates a label. He explains it something along the lines as the threads overwriting each other causing the program to crash with an IllegalStateException. What I don't understand is Threads overwriting each other is not uncommon and just makes the program behave in ways not intended and doesn't usually completely crash the program.
  In this case the threads are both trying to change the label to the same String. 
  Why is this throwing an IllegalStateException instead of just causing the usual interference? After all more than one thread trying to update an object doesn't necessarily crash the program.
  tl:dr Why does more than one thread modifying a Label object throw an IllegalStateException in this case but in other multi-threaded programs you just get the usual thread interference? The method of interest is the onButtonClicked() method.</p>
  
  <p>I have tried catching the IllegalStateException to see if I can call Thread.currentThread().getName() but the catch block(both of them actually) seem to get ignored.</p>
  
  <p>public class Controller {</p>
  
  <pre><code>@FXML
  private TextField nameField;
  @FXML
  private Button helloButton;
  @FXML
  private Button byeButton;
  @FXML
  private CheckBox ourCheckBox;
  @FXML
  private Label ourLabel;
  
  @FXML
  public void initialize() {
      helloButton.setDisable(true);
      byeButton.setDisable(true);
  }
  @FXML
  public void onButtonClicked(ActionEvent event) {
      if (event.getSource().equals(helloButton)) {
          System.out.println("hello, " + nameField.getText());
      } else if (event.getSource().equals(byeButton)) {
          System.out.println("Bye, " + nameField.getText());
      }
  
      Runnable task = new Runnable() {
          @Override
          public void run() {
              try {
                  Thread.sleep(5000);
                  ourLabel.setText("We did something");
              } catch (InterruptedException e) {
                  System.out.println("Interuppted Exception " + e.getMessage());
              } catch (IllegalStateException e) {
                  System.out.println("Illegal State Exception: " + e.getMessage() + " "
                      + Thread.currentThread().getName());
              }
          }
      };
      new Thread(task).start();
      if (ourCheckBox.isSelected()) {
          nameField.clear();
          byeButton.setDisable(true);
          helloButton.setDisable(true);
      }
  }
  
  @FXML
  public void handleKeyReleased() {
      String text = nameField.getText();
      boolean disableButtons = text.isEmpty() || text.trim().isEmpty();
      byeButton.setDisable(disableButtons);
      helloButton.setDisable(disableButtons);
  }
  
  @FXML
  public void handleChange() {
      System.out.println("The checkbox is " +
              (ourCheckBox.isSelected() ? "checked" : "not checked"));
  }
  </code></pre>
  
  <p>}</p>