Changes in Threading Model in the IntelliJ Platform 2026.1

Hello everyone,

We would like to share with you important updates to the threading framework in the IntelliJ Platform 2026.1.

In this release, we performed a series of application-wide semantic refactorings and adjusted several contracts governing how plugin code interacts with the UI. The overarching goal of these changes is to reduce the usage of the Read–Write Lock from the UI thread and make the platform more responsive and scalable.

The most important change in this release is the removal of the pre-acquired lock from the processing of AWT input events. In particular, custom user input handlers — such as java.awt.event.KeyListener#keyTyped or java.awt.event.MouseAdapter#mouseMoved — are no longer executed under the write-intent lock.
This is a breaking change. Previously, these listeners implicitly had read access and could freely interact with PSI. Starting with 2026.1, this is no longer the case. If your listener needs to access PSI, you must explicitly acquire the appropriate locking action (for example, using ReadAction.nonBlocking or WriteIntentReadAction.run).
The motivation behind this change is to enable input event processing without the Read–Write Lock when PSI access is not required. Many listeners do not interact with PSI at all, and they should not incur the associated locking cost. See IJPL-219144 for additional details.

Additionally, we are introducing several new APIs:

  • New method AnActionEvent#coroutineScope. AnAction#actionPerformed has a strict contract: it is invoked synchronously on the EDT in the input event that triggered the action. As the platform continues adopting Kotlin Coroutines, we now provide a convenient way to obtain a CoroutineScope inside actionPerformed, allowing actions to launch suspending computations while preserving the existing contract.

  • Backgroundable VFS Listeners. Historically, VFS listeners have to run on the UI thread. With the broader adoption of background write actions, it is now possible to execute these listeners in the background, improving IDE responsiveness. The newly introduced APIs are com.intellij.openapi.vfs.newvfs.BulkFileListenerBackgroundable and com.intellij.openapi.vfs.VirtualFileManager#addAsyncFileListenerBackgroundable.

Please note that these APIs are currently experimental. We expect them to stabilize in a future release.

1 Like

Additionally, we would like to highlight the fact that ReadAction.compute { }, ReadAction.run { }, runReadAction { } shortcuts have been deprecated.

Since the following APIs:

  • ReadAction.compute { … }
  • Application.runReadAction { … }
  • runReadAction { … }

are not cancellable by default.

When such a read action runs for a long time in a background thread, it can block write actions (PSI changes, workspace model updates, editor changes). Since many write actions are initiated by the UI thread, the result is a UI freeze, even though the work itself is “in the background”.

Recommended alternatives:

  • Use cancellable read actions - coroutines APIs: readAction/smartReadAction{}; ReadAction.nonBlocking{ … }.submit() or ReadAction.nonBlocking{ … }.executeSynchronously()) for Java code without coroutines.
  • For blocking, non-coroutine code: Split work into small predictable chunks. Run under ProgressManager.run(Task.Backgroundable){ … } with async progress and short read actions.
  • Periodically check for cancellation with ProgressManager.checkCanceled()
  • If absolutely needed, you will be able to use more verbose methods: ReadAction.computeBlocking and runReadActionBlocking, please keep them under modal progress or really short.

Stay tuned for a more detailed post on this soon.

2 Likes