# Refactoring for Java-Structured Concurrency
## 4 Design
### Precondition
#### 4.3.1 Precondition for _shutdownOnFailure_ Strategy  
_ShutdownOnFailure_ is a strategy in structured concurrency. It regards all the tasks as a whole and requires them to succeed together. Moreover, when one of the tasks fails, it cancels the remaining tasks that are running. In order to make the code before refactoring comply with this principle, we need to check the following two aspects: First, exceptions in subtasks should be captured in a timely manner in the main thread. In this way, the main thread can be aware of the execution status of the subtasks. Once a subtask fails, the failure of the entire concurrent task can be judged and dealt with. Second, the subtasks submitted should be independent of each other. The independence of subtasks is to prevent exceptions of one subtask from spreading and affecting other subtasks because of dependency relationships, thus ensuring that all the subtasks can be regarded as a whole. **Check task result acquisition**. In Java's multithreaded task return mechanism, when a task is submitted, a _Future_ object can be used to represent the returned result of the task. Using the method _Future.get_, we can obtain the result of the execution of the corresponding subtask or track the exception information from the subtask. If the method _Future.get_ is not  
Figure 4: The types of methods to be refactored. called in the main thread, even if an exception occurs in the subtask, it cannot be captured, as shown in Figure 5. The code snippet comes from the method _aggregateUnaryMatrix_ of the class _LibMatrixAgg_ in the project _SystemML_. In this code snippet, a fixed-sized thread pool is created, and a group of tasks is added to the task set (lines 2-10) first. Then, this group of tasks is submitted through the method _invokeAll_. Finally, the thread pool is closed (lines 11-12). However, this method does not obtain the returned result of _invokeAll_, so the main thread cannot use _future.get_ to obtain the exceptions or the results of the subtasks. Therefore, regardless of whether the subtasks are executed successfully, the main thread will continue to execute. This clearly violates the strategy _shutdownOnFailure_ in structured concurrency. Therefore, we need to determine whether a _Future_ object has been returned after all the subtasks are submitted. Then, we need to judge whether the results of the task have been obtained through _Future.get_ in the main thread. In this way, the main thread can capture exceptions in subtasks in a timely manner and terminate. **Check task dependency**. When converting from unstructured concurrency to structured concurrency, it is necessary to ensure independence between tasks. From the perspective of error propagation, independent tasks have no complicated dependencies and can directly terminate all the tasks according to the strategy _ShutdownOnFailure_ once a certain task fails. From the aspects of task scheduling and execution, in structured concurrency, the relationship between a parent task and subtasks is usually organized into a tree structure. This tree structure allows us to decompose complex tasks into a series of smaller subtasks, forming a clear hierarchical relationship. If the subtasks are independent of each other, it avoids mutual constraints in sibling tasks, enabling a more flexible organization and execution of tasks. In this way, structured concurrency can better manage and schedule tasks, improving the maintainability and execution efficiency of the program. Task dependency analysis aims to identify dependencies between subtasks in a multithreaded environment. In multithreaded programming, the dependencies in tasks are typically manifested as control and data dependencies. Control dependence refers to the relationship between the execution order among tasks. Data dependency refers to the potential competition that may arise when multiple tasks access or modify shared resources. Algorithm 1 presents the task dependency analysis, which takes the method \(m\) and the tasks in \(m\) as input.