March 11, 2025
Thread Interrupts in ColdFusion
Comments
(0)
March 11, 2025
Thread Interrupts in ColdFusion
Newbie 3 posts
Followers: 0 people
(0)

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It’s up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate. This is particularly useful in multi-threaded applications where you might want to gracefully stop a thread, handle a long-running task’s termination, or check for some condition periodically.

 
Why Use Interrupts?

  1. Graceful Termination: Interrupts provide a way to terminate threads cleanly, allowing them to perform any necessary cleanup.
  2. Responsiveness: Threads can periodically check if they have been interrupted and stop their execution, ensuring that the application remains responsive.
  3. Cooperation: Interrupts enable threads to cooperate with each other, providing a mechanism for safe and coordinated stopping.
 
Interrupting a Thread in ColdFusion:
 
A CFThread sends an interrupt by invoking on the InterruptThread(“threadname”) or InterruptThread() or using action=”interrupt” on cfthread tag for a thread to be interrupted. The interrupted thread support its own interruption.
 
When interrupt is called on a thread it sets interrupt status flag on CFThread. If a thread is blocked in an invocation of the ThreadJoin or sleep method, then its interrupt status will be cleared and it will receive a ThreadInterruptedException. Interrupting a thread that is not alive will not have any effect.
 
Checking for an Interrupt:
 
To check if a given thread has been interrupted we can use isThreadInterrupted(“threadname”) 
The interrupted status of the thread is unaffected by this method. A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
 
Thread interruption can also be checked using ThreadInterrupted() which checks whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. In other words, if this method were to be called twice in succession, the second call would return false (unless the current thread were interrupted again, after the first call had cleared its interrupted status and before the second call had examined it). A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
 
Now we will see how to use these to handle thread interruption
 
When the thread is blocked due to sleep or join and, if the InterruptThread() method of a thread is called at this time, the thread’s interrupt flag is set to true. Due to the blocked state, the interrupt flag will be cleared and an ThreadInterruptedException exception will be generated
 
<cfscript>
 
thread action="run" name="myThread" {

   try {
        while (true) {
            // execute tasks...
        }
    } catch (com.adobe.coldfusion.ThreadInterruptedException ie) {
        // catch ThreadInterruptedException, exit while(true) loop, the thread exits
    }
}

</cfscript>



When the thread is blocked, and is interrupted it generates a ThreadInterruptedException exception. The exception is captured outside of while(true), so that the while(true) loop is exited! And later we can gracefully clean and close. When the thread is blocked, and is interrupted it generates a ThreadInterruptedException exception. The exception is captured outside of while(true), so that the while(true) loop is exited! And later we can gracefully clean and close.

Usually, we interrupt the thread in running state by calling ThreadInterrupted()

ThreadInterrupted() will determine whether the thread’s interrupt status is true. it will return true if so and clears the flag. At this point, the while loop will exit.

 

<cfscript>
 
thread action="run" name="myThread" {
    try {
        // 1. if the interrupt flag is true, the thread will come out of loop and ready for graceful termination
        while (!ThreadInterrupted()) {
            // execute tasks...
        }
    } catch (com.adobe.coldfusion.ThreadInterruptedException ie) { 
        // 2. Thread must be in blocked state and throws InterruptedException, thread is ready for graceful termination
    }
}
</cfscript>

Example of Thread Interruption in Coldfusion

<cfscript>
        mythread = "DOWNLOAD_CF"
        variables.message="MAIN START at " & now() & "<br>"
      chunks = [] // simulating storage
        thread action="run" name="#mythread#" {
            i = 1;
             // simulating chunk storage 
            try {
                variables.message &= "Downloading Started !!" & now() & "<br>";
                    
                while( !isThreadInterrupted(mythread) AND i <= 10 ){ 

                    Sleep(1000); // Simulate downloading a chunk overnetwork
                    chunks[i] = "CF PART " & i 
                    variables.message &= "Downloading chunk " & i & " at "& now() &"<br>";
                    i++
                }
                

                if( i == 11 ){
                    variables.message &= "Download Complete !!";
                }else{
                    variables.message &= "Download Interrupted while running !!";
                }
            }catch(com.adobe.coldfusion.ThreadInterruptedException ex){
                // interruption occurred while in sleep so interrupt status would have been cleared
            variables.message &= "Download Interrupted while in sleep !!";variables.message &= "Download Interrupted while in sleep !!";
              interruptThread(); // resets interrupt status again to true
            }
            
          if( isThreadInterrupted(mythread) ){

// clear all chunks stored -- cleaning
                for( j = 1; j < i; j++ ){
                    chunks[j] = 0;
                }
                variables.message &= "Download Aborted !!" & "<br>";
            }
            
        } 
      sleep(randRange(5000,15000)) //
        interruptThread(mythread); // interrupt from user after random time between 5s to 15s, interrupt will not have any effect after thread has completed
        thread action="join"name=mythread {}
        writeOutput(variables.message)
        writedump(chunks)
</cfscript>

In the example above, we simulate downloading a file in chunks, while handling the possibility of an interruption from the user (or another source). We create a new thread (myThread) which is responsible for downloading the file in chunks. The simulation involves checking whether the thread has been interrupted during the process and ensuring that it is handled gracefully.

A new thread, myThread, is started. Inside the thread, a while loop runs, downloading chunks of the file sequentially. Each chunk of the file is downloaded by performing some work (such as setting values like chunks[i] = "CF PART " & i). After downloading each chunk, the thread sleeps for a short period before continuing the download. In each iteration of the loop, the thread checks if it has been interrupted. If it has not been interrupted, the thread continues downloading the next chunk. If the user interrupts the thread before all chunks are downloaded, the interruption is handled in two main scenarios:

Scenario 1: Thread is Running

If the thread is executing a line of code (such as chunks[i] = "CF PART " & i), and the user interrupts the thread:

  • The thread’s interrupt status is set to true, but the current line of code will continue to execute.
  • The thread will complete the execution of the current block of code before checking the interrupt status again.
  • After finishing the current block of code, the thread checks the condition in the while loop (using isThreadInterrupted method).
  • Since the interrupt status was not checked while executing the line, the method isThreadInterrupted will return false, and the thread will exit the loop.

Note: This can result in the interruption being ignored for that specific chunk.

Scenario 2: Thread is Blocked (e.g., Sleeping)

If the thread is blocked on a line (such as Sleep(1000)), and the user interrupts the thread:

  • The interrupt status is set to true immediately upon interruption.
  • The ThreadInterruptedException is thrown, which clears the interrupt status.
  • The exception is caught by a catch block, where you can perform any necessary cleanup or additional handling.
  • Optionally, you can reset the interrupt status to true using interruptThread to maintain the interruption flag for future tasks or cleanup.

Note: This allows for a more immediate response to interruption, as the thread is unable to proceed when it is blocked during sleep.

After this we check for thread interruption using isThreadInterrupted and cleanup all the resources which leads to graceful termination of this thread.
0 Comments
Add Comment