*&---------------------------------------------------------------------* *& Report ZPARALLEL_DEMO1 *&---------------------------------------------------------------------* *& Description: 基于STARTING NEW TASK的多线程测试demo *& Author: DeveloperMrMeng *& Date: 2025.03.03 *&---------------------------------------------------------------------* REPORT zparallel_demo1. DATA: gt_request TYPE bapiret2_t, gt_response_seq TYPE bapiret2_t, gt_response_para TYPE bapiret2_t, gv_diff_seconds_seq TYPE timestampl, gv_diff_seconds_para TYPE timestampl. START-OF-SELECTION. PERFORM ready_test_data. PERFORM sequence_process. PERFORM parallel_process. cl_demo_output=>new( )->write( |Diffrence Seconds: { gv_diff_seconds_seq }| )->write( gt_response_seq )->write( |Diffrence Seconds: { gv_diff_seconds_para }| )->write( gt_response_para )->display( ). *&---------------------------------------------------------------------* *& Form ready_test_data *&---------------------------------------------------------------------* *& 准备测试数据 *&---------------------------------------------------------------------* FORM ready_test_data . DATA: ls_request TYPE bapiret2, lv_index TYPE sy-index. DO 5 TIMES. lv_index = sy-index. DO lv_index TIMES. ls_request-number = lv_index. APPEND ls_request TO gt_request. ENDDO. ENDDO. ENDFORM. *&---------------------------------------------------------------------* *& Form sequence_process *&---------------------------------------------------------------------* *& 顺序执行 *&---------------------------------------------------------------------* FORM sequence_process . DATA lt_response TYPE bapiret2_t. GET TIME STAMP FIELD DATA(lv_timestamp_begin). LOOP AT gt_request INTO DATA(ls_request). * 模拟数据库提交操作 CALL FUNCTION 'ZPARA_SLEEP_TEST' EXPORTING wait_time = 1 IMPORTING status = ls_request-type EXCEPTIONS internal_error = 1 OTHERS = 2. APPEND ls_request TO lt_response. ENDLOOP. gt_response_seq = lt_response. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_seq = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& Form parallel_process *&---------------------------------------------------------------------* *& 多线程执行 *&---------------------------------------------------------------------* FORM parallel_process . DATA: lt_response TYPE bapiret2_t, lv_task_name TYPE string, lv_snd_jobs TYPE i, lv_rcv_jobs TYPE i, lv_exc_flag TYPE i, lv_message TYPE char80, lv_wait_time TYPE int2. GET TIME STAMP FIELD DATA(lv_timestamp_begin). LOOP AT gt_request ASSIGNING FIELD-SYMBOL(<ls_request>). lv_task_name = 'Task' && sy-tabix. <ls_request>-parameter = lv_task_name. IF lv_task_name = 'Task8'. lv_wait_time = 2. ELSE. lv_wait_time = 1. ENDIF. * 模拟数据库提交操作 CALL FUNCTION 'ZPARA_SLEEP_TEST' STARTING NEW TASK lv_task_name DESTINATION IN GROUP DEFAULT PERFORMING call_back_form ON END OF TASK EXPORTING wait_time = lv_wait_time EXCEPTIONS system_failure = 1 MESSAGE lv_message communication_failure = 2 MESSAGE lv_message resource_failure = 3. CASE sy-subrc. WHEN 0. lv_snd_jobs += 1. WHEN 1 OR 2. WRITE lv_message. WHEN 3. IF lv_snd_jobs >= 1 AND lv_exc_flag = 0. lv_exc_flag = 1. WAIT UNTIL lv_rcv_jobs >= lv_snd_jobs UP TO 5 SECONDS. ENDIF. IF sy-subrc = 0. lv_exc_flag = 0. ELSE. WRITE 'Resource failure'. ENDIF. WHEN OTHERS. WRITE 'Other error'. ENDCASE. ENDLOOP. WAIT UNTIL lv_rcv_jobs >= lv_snd_jobs. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_para = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& Form call_back_form *&---------------------------------------------------------------------* *& 回调函数 *&---------------------------------------------------------------------* FORM call_back_form USING uv_taskname. DATA: ls_reponse TYPE bapiret2. RECEIVE RESULTS FROM FUNCTION 'ZPARA_SLEEP_TEST' IMPORTING status = ls_reponse-type EXCEPTIONS internal_error = 1. ls_reponse-parameter = uv_taskname. APPEND ls_reponse TO gt_response_para. CLEAR ls_reponse. ENDFORM.
基于SPTA框架
*&---------------------------------------------------------------------* *& Report ZPARALLEL_DEMO2 *&---------------------------------------------------------------------* *& Description: 基于SPTA框架的多线程测试demo *& Author: DeveloperMrMeng *& Date: 2025.03.03 *&---------------------------------------------------------------------* REPORT zparallel_demo2. DATA: gt_request TYPE bapiret2_t, gt_response_seq TYPE bapiret2_t, gt_response_para TYPE bapiret2_t, gv_diff_seconds_seq TYPE timestampl, gv_diff_seconds_para TYPE timestampl. START-OF-SELECTION. PERFORM ready_test_data. PERFORM sequence_process. PERFORM parallel_process. cl_demo_output=>new( )->write( |Diffrence Seconds: { gv_diff_seconds_seq }| )->write( gt_response_seq )->write( |Diffrence Seconds: { gv_diff_seconds_para }| )->write( gt_response_para )->display( ). *&---------------------------------------------------------------------* *& Form ready_test_data *&---------------------------------------------------------------------* *& 准备测试数据 *&---------------------------------------------------------------------* FORM ready_test_data . DATA: ls_request TYPE bapiret2, lv_index TYPE sy-index. DO 5 TIMES. lv_index = sy-index. DO lv_index TIMES. ls_request-number = lv_index. APPEND ls_request TO gt_request. ENDDO. ENDDO. ENDFORM. *&---------------------------------------------------------------------* *& Form sequence_process *&---------------------------------------------------------------------* *& 顺序执行 *&---------------------------------------------------------------------* FORM sequence_process . DATA lt_response TYPE bapiret2_t. GET TIME STAMP FIELD DATA(lv_timestamp_begin). LOOP AT gt_request INTO DATA(ls_request). * 模拟数据库提交操作 CALL FUNCTION 'ZPARA_SLEEP_TEST' EXPORTING wait_time = 1 IMPORTING status = ls_request-type EXCEPTIONS internal_error = 1 OTHERS = 2. APPEND ls_request TO lt_response. ENDLOOP. gt_response_seq = lt_response. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_seq = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& Form parallel_process *&---------------------------------------------------------------------* *& 多线程执行 *&---------------------------------------------------------------------* FORM parallel_process . DATA: lt_response TYPE bapiret2_t, lv_task_name TYPE string, lv_snd_jobs TYPE i, lv_rcv_jobs TYPE i, lv_exc_flag TYPE i, lv_message TYPE char80, lv_wait_time TYPE int2. DATA: lv_sergroup TYPE spta_rfcgr, lv_rfcgroup TYPE rzlli_apcl. CALL 'C_SAPGPARAM' "#EC CI_CCALL ID 'NAME' FIELD 'rdisp/myname' ID 'VALUE' FIELD lv_sergroup. SELECT SINGLE classname INTO lv_rfcgroup FROM rzllitab WHERE grouptype = 'S' AND applserver = lv_sergroup. IF sy-subrc <> 0. MESSAGE 'Server Group Read Error. Contact Administrator.' TYPE 'E'. ENDIF. GET TIME STAMP FIELD DATA(lv_timestamp_begin). CALL FUNCTION 'SPTA_PARA_PROCESS_START_2' EXPORTING server_group = lv_rfcgroup before_rfc_callback_form = 'BEFORE_RFC_CALLBACK_FORM' in_rfc_callback_form = 'IN_RFC_CALLBACK_FORM' after_rfc_callback_form = 'AFTER_RFC_CALLBACK_FORM' callback_prog = sy-repid CHANGING user_param = gt_request EXCEPTIONS invalid_server_group = 1 no_resources_available = 2 OTHERS = 3. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_para = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& Form parallel_process *&---------------------------------------------------------------------* FORM before_rfc_callback_form USING us_before_rfc_imp TYPE spta_t_before_rfc_imp CHANGING cs_before_rfc_exp TYPE spta_t_before_rfc_exp ct_rfcdata TYPE spta_t_indxtab ct_failed_objects TYPE spta_t_failed_objects ct_objects_in_task TYPE spta_t_pending_objects ct_user_param TYPE bapiret2_t. DATA: lv_package_size TYPE i, lv_counter TYPE i, lt_request TYPE bapiret2_t. lv_package_size = 1. * 按实际需求进行分批,比如同一订单号为一批数据,此处为了测试按照每条数据都并行处理 LOOP AT ct_user_param INTO DATA(ls_user_param). IF lv_counter < lv_package_size. APPEND ls_user_param TO lt_request. DELETE ct_user_param INDEX 1. lv_counter += 1. ELSE. EXIT. ENDIF. ENDLOOP. * 将数据转换为SPTA框架所需要的类型 CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE' EXPORTING data = lt_request IMPORTING indxtab = ct_rfcdata. IF lt_request IS NOT INITIAL. cs_before_rfc_exp-start_rfc = 'X'. ELSE. cs_before_rfc_exp-start_rfc = ''. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form in_rfc_callback_form *&---------------------------------------------------------------------* FORM in_rfc_callback_form USING us_in_rfc_imp TYPE spta_t_in_rfc_imp CHANGING cs_in_rfc_exp TYPE spta_t_in_rfc_exp ct_rfcdata TYPE spta_t_indxtab. DATA: lt_request TYPE bapiret2_t, lv_wait_time TYPE int2. * 将数据转换为实际处理所需要的可读类型 CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE' EXPORTING indxtab = ct_rfcdata IMPORTING data = lt_request. * 模拟数据库提交操作 LOOP AT lt_request ASSIGNING FIELD-SYMBOL(<ls_request>). * 模拟某条数据处理较慢 IF <ls_request>-number = 1. lv_wait_time = 2. ELSE. lv_wait_time = 1. ENDIF. * 模拟业务数据执行 CALL FUNCTION 'ZPARA_SLEEP_TEST' EXPORTING wait_time = lv_wait_time IMPORTING status = <ls_request>-type EXCEPTIONS internal_error = 1 OTHERS = 2. ENDLOOP. * 将数据转换为SPTA框架所需要的类型 CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE' EXPORTING data = lt_request IMPORTING indxtab = ct_rfcdata. ENDFORM. *&---------------------------------------------------------------------* *& Form after_rfc_callback_form *&---------------------------------------------------------------------* FORM after_rfc_callback_form USING ut_rfcdata TYPE spta_t_indxtab uv_rfcsubrc TYPE sy-subrc uv_rfcmsg TYPE spta_t_rfcmsg ut_objects_in_task TYPE spta_t_pending_objects us_after_rfc_imp TYPE spta_t_after_rfc_imp CHANGING cs_after_rfc_exp TYPE spta_t_after_rfc_exp ct_user_param TYPE bapiret2_t. DATA: lt_request TYPE bapiret2_t. * 将数据转换为实际处理所需要的可读类型 CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE' EXPORTING indxtab = ut_rfcdata IMPORTING data = lt_request. APPEND LINES OF lt_request TO gt_response_para. ENDFORM.
基于CL_ABAP_PARALLEL
*&---------------------------------------------------------------------* *& Report ZPARALLEL_DEMO3 *&---------------------------------------------------------------------* *& Description: 基于CL_ABAP_PARALLEL类的多线程测试demo *& Author: DeveloperMrMeng *& Date: 2025.03.03 *&---------------------------------------------------------------------* REPORT zparallel_demo3. *&---------------------------------------------------------------------* *& CLASS zcl_abap_parallel definition *&---------------------------------------------------------------------* CLASS zcl_abap_parallel DEFINITION INHERITING FROM cl_abap_parallel FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS do REDEFINITION. ENDCLASS. DATA: gt_request TYPE bapiret2_t, gt_response_seq TYPE bapiret2_t, gt_response_para TYPE bapiret2_t, gv_diff_seconds_seq TYPE timestampl, gv_diff_seconds_para TYPE timestampl. START-OF-SELECTION. PERFORM ready_test_data. PERFORM sequence_process. PERFORM parallel_process. cl_demo_output=>new( )->write( |Diffrence Seconds: { gv_diff_seconds_seq }| )->write( gt_response_seq )->write( |Diffrence Seconds: { gv_diff_seconds_para }| )->write( gt_response_para )->display( ). *&---------------------------------------------------------------------* *& Form ready_test_data *&---------------------------------------------------------------------* *& 准备测试数据 *&---------------------------------------------------------------------* FORM ready_test_data . DATA: ls_request TYPE bapiret2, lv_index TYPE sy-index. DO 5 TIMES. lv_index = sy-index. DO lv_index TIMES. ls_request-number = lv_index. APPEND ls_request TO gt_request. ENDDO. ENDDO. ENDFORM. *&---------------------------------------------------------------------* *& Form sequence_process *&---------------------------------------------------------------------* *& 顺序执行 *&---------------------------------------------------------------------* FORM sequence_process . DATA lt_response TYPE bapiret2_t. GET TIME STAMP FIELD DATA(lv_timestamp_begin). LOOP AT gt_request INTO DATA(ls_request). * 模拟数据库提交操作 CALL FUNCTION 'ZPARA_SLEEP_TEST' EXPORTING wait_time = 1 IMPORTING status = ls_request-type EXCEPTIONS internal_error = 1 OTHERS = 2. APPEND ls_request TO lt_response. ENDLOOP. gt_response_seq = lt_response. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_seq = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& Form parallel_process *&---------------------------------------------------------------------* *& 多线程执行 *&---------------------------------------------------------------------* FORM parallel_process . DATA: lt_in_xstring TYPE xstring, lt_in TYPE cl_abap_parallel=>t_in_tab, lt_out TYPE cl_abap_parallel=>t_out_tab, lt_response TYPE bapiret2_t, lt_request TYPE bapiret2_t. GET TIME STAMP FIELD DATA(lv_timestamp_begin). * 按实际需求进行分批,比如同一订单号为一批数据,此处为了测试按照每条数据都并行处理 LOOP AT gt_request INTO DATA(ls_request). APPEND ls_request TO lt_request. * 将数据转换为接口所需要的类型 CALL TRANSFORMATION id SOURCE in = lt_request RESULT XML lt_in_xstring. INSERT lt_in_xstring INTO TABLE lt_in. CLEAR: lt_request, lt_in_xstring. ENDLOOP. * p_percentage参数用来指定可用进程百分比,可以指定为0~100 DATA(lo_parallel) = NEW zcl_abap_parallel( p_percentage = 95 ). * 多线程启动 lo_parallel->run( EXPORTING p_in_tab = lt_in IMPORTING p_out_tab = lt_out ). * 解析执行结果 LOOP AT lt_out INTO DATA(ls_out). * 将数据转换为实际处理所需要的可读类型 CALL TRANSFORMATION id SOURCE XML ls_out-result RESULT out = lt_response. INSERT LINES OF lt_response INTO TABLE gt_response_para. CLEAR lt_response. ENDLOOP. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_para = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& CLASS zcl_abap_parallel implementation *&---------------------------------------------------------------------* CLASS zcl_abap_parallel IMPLEMENTATION. METHOD do. DATA: lt_request TYPE bapiret2_t, lv_wait_time TYPE int2. * 将数据转换为实际处理所需要的可读类型 CALL TRANSFORMATION id SOURCE XML p_in RESULT in = lt_request. LOOP AT lt_request ASSIGNING FIELD-SYMBOL(<ls_request>). * 模拟某条数据处理较慢 IF <ls_request>-number = 1. lv_wait_time = 2. ELSE. lv_wait_time = 1. ENDIF. * 模拟业务数据执行 CALL FUNCTION 'ZPARA_SLEEP_TEST' EXPORTING wait_time = lv_wait_time IMPORTING status = <ls_request>-type EXCEPTIONS internal_error = 1 OTHERS = 2. ENDLOOP. * 将数据转换为接口所需要的类型 CALL TRANSFORMATION id SOURCE out = lt_request RESULT XML p_out. ENDMETHOD. ENDCLASS.
基于IF_ABAP_PARALLEL
*&---------------------------------------------------------------------* *& Report ZPARALLEL_DEMO4 *&---------------------------------------------------------------------* *& Description: 基于IF_ABAP_PARALLEL接口的多线程测试demo *& Author: DeveloperMrMeng *& Date: 2025.03.03 *&---------------------------------------------------------------------* REPORT zparallel_demo4. *&---------------------------------------------------------------------* *& CLASS zcl_abap_parallel definition *&---------------------------------------------------------------------* CLASS zcl_abap_parallel DEFINITION. PUBLIC SECTION. INTERFACES if_abap_parallel . INTERFACES if_serializable_object . METHODS constructor IMPORTING VALUE(it_request) TYPE bapiret2_t . METHODS get_response EXPORTING VALUE(it_response) TYPE bapiret2_t. PROTECTED SECTION. PRIVATE SECTION. DATA: mt_request TYPE bapiret2_t, mt_response TYPE bapiret2_t. ENDCLASS. DATA: gt_request TYPE bapiret2_t, gt_response_seq TYPE bapiret2_t, gt_response_para TYPE bapiret2_t, gv_diff_seconds_seq TYPE timestampl, gv_diff_seconds_para TYPE timestampl. START-OF-SELECTION. PERFORM ready_test_data. PERFORM sequence_process. PERFORM parallel_process. cl_demo_output=>new( )->write( |Diffrence Seconds: { gv_diff_seconds_seq }| )->write( gt_response_seq )->write( |Diffrence Seconds: { gv_diff_seconds_para }| )->write( gt_response_para )->display( ). *&---------------------------------------------------------------------* *& Form ready_test_data *&---------------------------------------------------------------------* *& 准备测试数据 *&---------------------------------------------------------------------* FORM ready_test_data . DATA: ls_request TYPE bapiret2, lv_index TYPE sy-index. DO 5 TIMES. lv_index = sy-index. DO lv_index TIMES. ls_request-number = lv_index. APPEND ls_request TO gt_request. ENDDO. ENDDO. ENDFORM. *&---------------------------------------------------------------------* *& Form sequence_process *&---------------------------------------------------------------------* *& 顺序执行 *&---------------------------------------------------------------------* FORM sequence_process . DATA lt_response TYPE bapiret2_t. GET TIME STAMP FIELD DATA(lv_timestamp_begin). LOOP AT gt_request INTO DATA(ls_request). * 模拟数据库提交操作 CALL FUNCTION 'ZPARA_SLEEP_TEST' EXPORTING wait_time = 1 IMPORTING status = ls_request-type EXCEPTIONS internal_error = 1 OTHERS = 2. APPEND ls_request TO lt_response. ENDLOOP. gt_response_seq = lt_response. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_seq = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& Form parallel_process *&---------------------------------------------------------------------* *& 多线程执行 *&---------------------------------------------------------------------* FORM parallel_process . DATA: lt_response TYPE bapiret2_t, lt_request TYPE bapiret2_t, lt_in_tab TYPE cl_abap_parallel=>t_in_inst_tab, lt_out_tab TYPE cl_abap_parallel=>t_out_inst_tab. GET TIME STAMP FIELD DATA(lv_timestamp_begin). * 按实际需求进行分批,比如同一订单号为一批数据,此处为了测试按照每条数据都并行处理 LOOP AT gt_request INTO DATA(ls_request). APPEND ls_request TO lt_request. * 将打包好的数据依次构建传入参数 INSERT NEW zcl_abap_parallel( lt_request ) INTO TABLE lt_in_tab. CLEAR lt_request. ENDLOOP. * p_percentage参数用来指定可用进程百分比,可以指定为0~100 NEW cl_abap_parallel( p_percentage = 95 )->run_inst( EXPORTING p_in_tab = lt_in_tab IMPORTING p_out_tab = lt_out_tab ). * 解析执行结果 LOOP AT lt_out_tab INTO DATA(ls_out_tab). CAST zcl_abap_parallel( ls_out_tab-inst )->get_response( IMPORTING it_response = lt_response ). APPEND LINES OF lt_response TO gt_response_para. CLEAR lt_response. ENDLOOP. GET TIME STAMP FIELD DATA(lv_timestamp_end). gv_diff_seconds_para = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp_end tstmp2 = lv_timestamp_begin ). ENDFORM. *&---------------------------------------------------------------------* *& CLASS zcl_abap_parallel implementation *&---------------------------------------------------------------------* CLASS zcl_abap_parallel IMPLEMENTATION. * 构造方法 METHOD constructor. mt_request = it_request. ENDMETHOD. * 实际逻辑处理 METHOD if_abap_parallel~do. DATA: lv_wait_time TYPE int2. LOOP AT mt_request ASSIGNING FIELD-SYMBOL(<ls_request>). * 模拟某条数据处理较慢 IF <ls_request>-number = 1. lv_wait_time = 2. ELSE. lv_wait_time = 1. ENDIF. * 模拟业务数据执行 CALL FUNCTION 'ZPARA_SLEEP_TEST' EXPORTING wait_time = lv_wait_time IMPORTING status = <ls_request>-type EXCEPTIONS internal_error = 1 OTHERS = 2. ENDLOOP. * 返回处理结果 mt_response = mt_request. ENDMETHOD. * 获取处理结果 METHOD get_response. it_response = mt_response. ENDMETHOD. ENDCLASS.