1e41f4b71Sopenharmony_ci# CPU Intensive Task Development (TaskPool and Worker)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciCPU intensive tasks are tasks that occupy a significant amount of system computing resources and that may block other tasks in the same thread. Example CPU intensive tasks are image processing, video encoding, and data analysis.
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciTo improve CPU utilization and application response speeds, use multithread concurrency in processing CPU intensive tasks.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ciIf a task can be completed in a background thread within 3 minutes, you are advised to use TaskPool. Otherwise, use Worker. The following uses histogram processing and a time-consuming model prediction task in the background as examples.
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci## Using TaskPool to Process Histograms
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci1. Implement the logic of image processing.
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci2. Segment the data, and initiate associated task scheduling through task groups.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci   Create a [task group](../reference/apis-arkts/js-apis-taskpool.md#taskgroup10), call [addTask()](../reference/apis-arkts/js-apis-taskpool.md#addtask10) to add tasks, and call [execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute10) to execute the tasks in the task group at a [a high priority](../reference/apis-arkts/js-apis-taskpool.md#priority). After all the tasks in the task group are complete, the histogram processing result is returned simultaneously.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci3. Summarize and process the result arrays.
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci```ts
24e41f4b71Sopenharmony_ciimport { taskpool } from '@kit.ArkTS';
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci@Concurrent
27e41f4b71Sopenharmony_cifunction imageProcessing(dataSlice: ArrayBuffer): ArrayBuffer {
28e41f4b71Sopenharmony_ci  // Step 1: Perform specific image processing operations and other time-consuming operations.
29e41f4b71Sopenharmony_ci  return dataSlice;
30e41f4b71Sopenharmony_ci}
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_cifunction histogramStatistic(pixelBuffer: ArrayBuffer): void {
33e41f4b71Sopenharmony_ci  // Step 2: Perform concurrent scheduling for data in three segments.
34e41f4b71Sopenharmony_ci  let number: number = pixelBuffer.byteLength / 3;
35e41f4b71Sopenharmony_ci  let buffer1: ArrayBuffer = pixelBuffer.slice(0, number);
36e41f4b71Sopenharmony_ci  let buffer2: ArrayBuffer = pixelBuffer.slice(number, number * 2);
37e41f4b71Sopenharmony_ci  let buffer3: ArrayBuffer = pixelBuffer.slice(number * 2);
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci  let group: taskpool.TaskGroup = new taskpool.TaskGroup();
40e41f4b71Sopenharmony_ci  group.addTask(imageProcessing, buffer1);
41e41f4b71Sopenharmony_ci  group.addTask(imageProcessing, buffer2);
42e41f4b71Sopenharmony_ci  group.addTask(imageProcessing, buffer3);
43e41f4b71Sopenharmony_ci
44e41f4b71Sopenharmony_ci  taskpool.execute(group, taskpool.Priority.HIGH).then((ret: Object) => {
45e41f4b71Sopenharmony_ci    // Step 3: Summarize and process the result arrays.
46e41f4b71Sopenharmony_ci  })
47e41f4b71Sopenharmony_ci}
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci@Entry
50e41f4b71Sopenharmony_ci@Component
51e41f4b71Sopenharmony_cistruct Index {
52e41f4b71Sopenharmony_ci  @State message: string = 'Hello World'
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ci  build() {
55e41f4b71Sopenharmony_ci    Row() {
56e41f4b71Sopenharmony_ci      Column() {
57e41f4b71Sopenharmony_ci        Text(this.message)
58e41f4b71Sopenharmony_ci          .fontSize(50)
59e41f4b71Sopenharmony_ci          .fontWeight(FontWeight.Bold)
60e41f4b71Sopenharmony_ci          .onClick(() => {
61e41f4b71Sopenharmony_ci            let buffer: ArrayBuffer = new ArrayBuffer(24);
62e41f4b71Sopenharmony_ci            histogramStatistic(buffer);
63e41f4b71Sopenharmony_ci          })
64e41f4b71Sopenharmony_ci      }
65e41f4b71Sopenharmony_ci      .width('100%')
66e41f4b71Sopenharmony_ci    }
67e41f4b71Sopenharmony_ci    .height('100%')
68e41f4b71Sopenharmony_ci  }
69e41f4b71Sopenharmony_ci}
70e41f4b71Sopenharmony_ci```
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci
73e41f4b71Sopenharmony_ci## Using Worker for Time-Consuming Model Prediction
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ciThe following uses the training of a region-specific house price prediction model as an example. This model can be used to predict house prices in the region based on the house area and number of rooms. The model needs to run for a long time, and each prediction needs to use the previous running result. Due to these considerations, Worker is used for the development.
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ci1. In DevEco Studio, add a worker named **MyWorker** to your project.
78e41f4b71Sopenharmony_ci
79e41f4b71Sopenharmony_ci   ![newWorker](figures/newWorker.png)
80e41f4b71Sopenharmony_ci
81e41f4b71Sopenharmony_ci2. In the main thread, call [constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9) of **ThreadWorker** to create a **Worker** object. The calling thread is the host thread.
82e41f4b71Sopenharmony_ci
83e41f4b71Sopenharmony_ci    ```ts
84e41f4b71Sopenharmony_ci    // Index.ets
85e41f4b71Sopenharmony_ci    import { worker } from '@kit.ArkTS';
86e41f4b71Sopenharmony_ci
87e41f4b71Sopenharmony_ci    const workerInstance: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');
88e41f4b71Sopenharmony_ci    ```
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ci3. In the host thread, call [onmessage()](../reference/apis-arkts/js-apis-worker.md#onmessage9) to receive messages from the worker thread, and call [postMessage()](../reference/apis-arkts/js-apis-worker.md#postmessage9) to send messages to the worker thread.
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci   For example, the host thread sends training and prediction messages to the worker thread, and receives messages sent back by the worker thread.
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_ci    ```ts
95e41f4b71Sopenharmony_ci    // Index.ets
96e41f4b71Sopenharmony_ci    let done = false;
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci    // Receive the result from the worker thread.
99e41f4b71Sopenharmony_ci    workerInstance.onmessage = (() => {
100e41f4b71Sopenharmony_ci      console.info('MyWorker.ts onmessage');
101e41f4b71Sopenharmony_ci      if (!done) {
102e41f4b71Sopenharmony_ci        workerInstance.postMessage({ 'type': 1, 'value': 0 });
103e41f4b71Sopenharmony_ci        done = true;
104e41f4b71Sopenharmony_ci      }
105e41f4b71Sopenharmony_ci    })
106e41f4b71Sopenharmony_ci
107e41f4b71Sopenharmony_ci    workerInstance.onerror = (() => {
108e41f4b71Sopenharmony_ci      // Receive error information from the worker thread.
109e41f4b71Sopenharmony_ci    })
110e41f4b71Sopenharmony_ci
111e41f4b71Sopenharmony_ci    // Send a training message to the worker thread.
112e41f4b71Sopenharmony_ci    workerInstance.postMessage({ 'type': 0 });
113e41f4b71Sopenharmony_ci    ```
114e41f4b71Sopenharmony_ci
115e41f4b71Sopenharmony_ci4. Bind the **Worker** object in the **MyWorker.ts** file. The calling thread is the worker thread.
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ci   ```ts
118e41f4b71Sopenharmony_ci   // MyWorker.ts
119e41f4b71Sopenharmony_ci   import { worker, ThreadWorkerGlobalScope, MessageEvents, ErrorEvent } from '@kit.ArkTS';
120e41f4b71Sopenharmony_ci
121e41f4b71Sopenharmony_ci   let workerPort: ThreadWorkerGlobalScope = worker.workerPort;
122e41f4b71Sopenharmony_ci   ```
123e41f4b71Sopenharmony_ci
124e41f4b71Sopenharmony_ci5. In the worker thread, call [onmessage()](../reference/apis-arkts/js-apis-worker.md#onmessage9-1) to receive messages sent by the host thread, and call [postMessage()](../reference/apis-arkts/js-apis-worker.md#postmessage9-2) to send messages to the host thread.
125e41f4b71Sopenharmony_ci
126e41f4b71Sopenharmony_ci    For example, the prediction model and its training process are defined in the worker thread, and messages are exchanged with the main thread.
127e41f4b71Sopenharmony_ci
128e41f4b71Sopenharmony_ci    ```ts
129e41f4b71Sopenharmony_ci    // MyWorker.ts
130e41f4b71Sopenharmony_ci    // Define the training model and result.
131e41f4b71Sopenharmony_ci    let result: Array<number>;
132e41f4b71Sopenharmony_ci    // Define the prediction function.
133e41f4b71Sopenharmony_ci    function predict(x: number): number {
134e41f4b71Sopenharmony_ci     return result[x];
135e41f4b71Sopenharmony_ci    }
136e41f4b71Sopenharmony_ci    // Define the optimizer training process.
137e41f4b71Sopenharmony_ci    function optimize(): void {
138e41f4b71Sopenharmony_ci     result = [0];
139e41f4b71Sopenharmony_ci    }
140e41f4b71Sopenharmony_ci    // onmessage logic of the worker thread.
141e41f4b71Sopenharmony_ci    workerPort.onmessage = (e: MessageEvents): void => {
142e41f4b71Sopenharmony_ci     // Perform operations based on the type of data to transmit.
143e41f4b71Sopenharmony_ci     switch (e.data.type as number) {
144e41f4b71Sopenharmony_ci      case 0:
145e41f4b71Sopenharmony_ci      // Perform training.
146e41f4b71Sopenharmony_ci       optimize();
147e41f4b71Sopenharmony_ci      // Send a training success message to the main thread after training is complete.
148e41f4b71Sopenharmony_ci       workerPort.postMessage({ type: 'message', value: 'train success.' });
149e41f4b71Sopenharmony_ci       break;
150e41f4b71Sopenharmony_ci      case 1:
151e41f4b71Sopenharmony_ci      // Execute the prediction.
152e41f4b71Sopenharmony_ci       const output: number = predict(e.data.value as number);
153e41f4b71Sopenharmony_ci      // Send the prediction result to the main thread.
154e41f4b71Sopenharmony_ci       workerPort.postMessage({ type: 'predict', value: output });
155e41f4b71Sopenharmony_ci       break;
156e41f4b71Sopenharmony_ci      default:
157e41f4b71Sopenharmony_ci       workerPort.postMessage({ type: 'message', value: 'send message is invalid' });
158e41f4b71Sopenharmony_ci       break;
159e41f4b71Sopenharmony_ci     }
160e41f4b71Sopenharmony_ci    }
161e41f4b71Sopenharmony_ci    ```
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ci6. After the task is completed in the worker thread, destroy the worker thread. The worker thread can be destroyed by itself or the host thread. Then, call [onexit()](../reference/apis-arkts/js-apis-worker.md#onexit9) in the host thread to define the processing logic after the worker thread is destroyed.
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci    ```ts
166e41f4b71Sopenharmony_ci    // After the worker thread is destroyed, execute the onexit() callback.
167e41f4b71Sopenharmony_ci    workerInstance.onexit = (): void => {
168e41f4b71Sopenharmony_ci     console.info("main thread terminate");
169e41f4b71Sopenharmony_ci    }
170e41f4b71Sopenharmony_ci    ```
171e41f4b71Sopenharmony_ci
172e41f4b71Sopenharmony_ci    Method 1: In the host thread, call [terminate()](../reference/apis-arkts/js-apis-worker.md#terminate9) to destroy the worker thread and stop the worker thread from receiving messages.
173e41f4b71Sopenharmony_ci
174e41f4b71Sopenharmony_ci    ```ts
175e41f4b71Sopenharmony_ci    // Destroy the worker thread.
176e41f4b71Sopenharmony_ci    workerInstance.terminate();
177e41f4b71Sopenharmony_ci    ```
178e41f4b71Sopenharmony_ci
179e41f4b71Sopenharmony_ci    Method 2: In the worker thread, call [close()](../reference/apis-arkts/js-apis-worker.md#close9) to destroy the worker thread and stop the worker thread from receiving messages.
180e41f4b71Sopenharmony_ci
181e41f4b71Sopenharmony_ci    ```ts
182e41f4b71Sopenharmony_ci    // Destroy the worker thread.
183e41f4b71Sopenharmony_ci    workerPort.close();
184e41f4b71Sopenharmony_ci    ```
185