Explain Codes LogoExplain Codes Logo

Running code in main thread from another thread

java
threading
concurrency
android
Anton ShumikhinbyAnton Shumikhin·Jan 16, 2025
TLDR

Execute code on the main thread while in a background thread with java.awt.EventQueue.invokeLater() for AWT/Swing GUI applications or Platform.runLater() for JavaFX. For general Java tasks, utilize CompletableFuture or the ExecutorService to schedule actions on the main thread.

AWT/Swing example:

java.awt.EventQueue.invokeLater(() -> { // Your code is like Spiderman, jumping back to the main thread here });

JavaFX example:

Platform.runLater(() -> { // Imagine this is the Batcave, where main-thread updates happen });

General Java:

CompletableFuture.runAsync(() -> { // Performing Sherlock's investigations in the background }).thenRun(() -> { // Reporting to Dr. Watson on the main thread when done });

These approaches can help maintain a responsive and consistent application.

Android's approach: Handlers and Loopers

Focusing on Android, the platform offers specific solutions for thread communication, like using a Handler with a Runnable:

new Handler(Looper.getMainLooper()).post(() -> { // Hulk smash!... I mean, update UI or perform main-thread work here });

Obtain the main thread's Looper using Looper.getMainLooper(), and always catch exceptions to prevent the Avenger, I mean app, from crashing due to main thread errors.

Playing the field: Services and Activities

In complex scenarios like services-activity communication, Bound Services and Broadcast Receivers are your go-to moves. Use EventBus for pub/sub patterns and recognize the differences in lifecycle and threading models when dealing with services and activities.

Cooperating tasks: Preventing Civil War

A multithreaded environment is a team of Avengers. Know where your Hawkeye is aiming to avoid deadlocks, performance bottlenecks, or any Civil War. Use concurrency constructs, such as CountDownLatch, CyclicBarrier, Future, and avoid letting Thanos snap his fingers.

The uncovered Infinity Stones

Java's concurrency API offers concurrency control mechanisms for more advanced use cases:

  • SynchronousQueue: Ideal for rendezvous channels.
  • Semaphore: The bouncer at the door for shared resources.
  • Phaser: The flexible friend for multi-phase tasks.

Kotlin's got you covered

Kotlin simplifies the process with ætherial ease, using coroutines:

CoroutineScope(Dispatchers.Main).launch { // This coroutine won't break any time continuum, promise }

Switch to the main thread using withContext(Dispatchers.Main) { }.