abap 多线程运行demo

SAP 提供多种多线程的方法去优化程序的执行效率

1.分别执行多个job

2.Call function STARTING NEW TASK

3.直接使用SAP 提供的SPTA 框架函数:SPTA_PARA_PROCESS_START_2

本次,我们着重来介绍一下三种方法中函数的使用方法

获取空闲线程数:SPBT_INITIALIZE

*&---------------------------------------------------------------------*
*& Report  ZDEMO_TEST_PARALLEL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT  zdemo_test_parallel.
TYPE-POOLS:spta.
DATA: gs_head  TYPE zsfi_doc_head.
DATA: gt_head  TYPE STANDARD TABLE OF zsfi_doc_head.
DATA: gt_out   TYPE STANDARD TABLE OF zsfi_doc_head_o.
DATA: gt_item  TYPE STANDARD TABLE OF zsfi_doc_item.
DATA: gs_item  TYPE zsfi_doc_item.
DATA: ls_head  TYPE zsfi_doc_head.
DATA: lt_head  TYPE STANDARD TABLE OF zsfi_doc_head.
DATA: lt_item  TYPE STANDARD TABLE OF zsfi_doc_item.
DATA: ls_item  TYPE zsfi_doc_item.
DATA: lv_int     TYPE numc4.
DATA: gs_parallel TYPE zsfi_doc_head_run.
DATA: gt_parallel TYPE ztfi_doc_head_run_t.
DATA: gt_result TYPE ztfi_doc_head_run_t.

DATA: gv_start TYPE char10.
DATA: gv_end   TYPE char10.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME  TITLE text-t01.
PARAMETERS: p_group TYPE spta_rfcgr OBLIGATORY MEMORY ID spta_rfcgr DEFAULT 'parallel_generators'.
PARAMETERS: p_task  LIKE sy-index DEFAULT '10'.
PARAMETERS: p_times TYPE numc4 OBLIGATORY DEFAULT '100'.
PARAMETERS: p_loop  TYPE char01 RADIOBUTTON GROUP rd1 DEFAULT 'X'.
PARAMETERS: p_para  TYPE char01 RADIOBUTTON GROUP rd1 .

SELECTION-SCREEN END OF BLOCK b1.

START-OF-SELECTION.
  lv_int = p_times.

  SELECT SINGLE *
  INTO CORRESPONDING FIELDS OF ls_head
  FROM ztfi_doc_head
  WHERE zsernr = 'BPM26020240606000003'.

  SELECT  *
  INTO CORRESPONDING FIELDS OF TABLE lt_item
  FROM ztfi_doc_item
  WHERE zsernr = 'BPM26020240606000003'.

  CASE 'X'.
    WHEN p_loop.
      PERFORM frm_loop_process.
    WHEN p_para.
      PERFORM frm_parallel_process.

    WHEN OTHERS.
  ENDCASE.


*&---------------------------------------------------------------------*
*&      Form  FRM_LOOP_PROCESS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_loop_process .

  DATA: lv_errcode TYPE char8.
  DATA: lv_errdesc TYPE char250.




  gv_start = sy-uzeit.

  IF  ls_head IS NOT INITIAL AND lt_item IS NOT INITIAL .
    DO p_times TIMES.
      lv_int = lv_int - 1.

      CLEAR:lv_errcode,lv_errdesc,gt_item,gt_head,gt_out.
      CONCATENATE  'BPM06020240612LOOP9' lv_int INTO ls_head-zsernr.
      CONCATENATE  '240606LOOP4' lv_int INTO ls_head-orderid.

      APPEND ls_head TO gt_head.

      LOOP AT  lt_item INTO ls_item .
        CONCATENATE 'BPM06020240612LOOP9' lv_int INTO ls_item-zsernr.
        APPEND ls_item TO gt_item.
      ENDLOOP.

      CALL FUNCTION 'ZFIFM_RECEIPT_POSTING'
        IMPORTING
          errcode = lv_errcode
          errdesc = lv_errdesc
        TABLES
          it_head = gt_head
          it_item = gt_item
          ot_head = gt_out.


    ENDDO.
  ENDIF.

  gv_end = sy-uzeit.

  WRITE gv_start.
  WRITE gv_end.


ENDFORM.                    " FRM_LOOP_PROCESS
*&---------------------------------------------------------------------*
*&      Form  FRM_PARALLEL_PROCESS
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_parallel_process .
  CLEAR:gt_parallel.
  DO p_times TIMES.
    lv_int = lv_int + 1.
    CLEAR:gt_item,gt_head,gs_parallel.
    CONCATENATE  'BPM06020240612PARALLEL9' lv_int INTO ls_head-zsernr.
    CONCATENATE  '240612PARAL9' lv_int INTO ls_head-orderid.

    MOVE-CORRESPONDING ls_head TO gs_parallel.

    LOOP AT  lt_item INTO ls_item .
      CONCATENATE 'BPM06020240612PARALLEL9' lv_int INTO ls_item-zsernr.
      APPEND ls_item TO gt_item.
    ENDLOOP.

    gs_parallel-item = gt_item.
    APPEND gs_parallel TO  gt_parallel.
  ENDDO.

  gv_start = sy-uzeit.

  CALL FUNCTION 'SPTA_PARA_PROCESS_START_2'
    EXPORTING
      server_group             = p_group
      max_no_of_tasks          = p_task
      before_rfc_callback_form = 'BEFORE_RFC'
      in_rfc_callback_form     = 'IN_RFC'
      after_rfc_callback_form  = 'AFTER_RFC'
      callback_prog            = sy-repid
    CHANGING
      user_param               = gt_parallel   "this is for you to transfer data you want to deal
    EXCEPTIONS
      invalid_server_group     = 1
      no_resources_available   = 2
      OTHERS                   = 3.

  gv_end = sy-uzeit.

  WRITE gv_start.
  WRITE gv_end.

ENDFORM.                    " FRM_PARALLEL_PROCESS

*&---------------------------------------------------------------------*
*&      Form  before_rfc
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->IS_BEFORE_RFC_IMP      text
*      -->CS_BEFORE_RFC_EXP      text
*      -->CT_RFCDATA            text
*      -->CT_FAILED_OBJECTS      text
*      -->CT_OBJECTS_IN_PROCESS  text
*      -->P_USER_PARAM          text
*----------------------------------------------------------------------*
FORM before_rfc    USING  is_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_process  TYPE spta_t_objects_in_process
                        ct_user_param          TYPE ztfi_doc_head_run_t.   " you own data

  DATA: ls_parallel TYPE zsfi_doc_head_run.
  DATA: lt_parallel TYPE STANDARD TABLE OF  zsfi_doc_head_run.
  DATA: lv_counter TYPE i.
  DATA: lv_package TYPE i.


* define the package size as 10
  lv_package = 10.
  CLEAR:lt_parallel.

  LOOP AT ct_user_param INTO gs_parallel.
    IF lv_counter < lv_package.
      APPEND gs_parallel TO lt_parallel.
      DELETE ct_user_param INDEX 1.
      lv_counter = lv_counter + 1.
    ELSE.
      EXIT.
    ENDIF.

  ENDLOOP.



* Convert the input data into the INDX structure that is needed for the RFC
  CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'
    EXPORTING
      data    = lt_parallel
    IMPORTING
      indxtab = ct_rfcdata.

  IF lt_parallel IS INITIAL.
    CLEAR cs_before_rfc_exp-start_rfc.
    EXIT.
  ELSE.
* Inform task manager that an RFC can be started from the
* data compiled
    cs_before_rfc_exp-start_rfc = 'X'.
  ENDIF.




ENDFORM.                    "before_rfc
*&---------------------------------------------------------------------*
*&      Form  in_rfc
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->IS_IN_RFC_IMP  text
*      -->ES_IN_RFC_EXP  text
*      -->IT_RFCDATA     text
*----------------------------------------------------------------------*
FORM in_rfc
        USING    is_in_rfc_imp TYPE spta_t_in_rfc_imp
        CHANGING es_in_rfc_exp TYPE spta_t_in_rfc_exp
                 ct_rfcdata    TYPE spta_t_indxtab.

  DATA: ls_head_temp  TYPE zsfi_doc_head.
  DATA: lt_head_temp  TYPE STANDARD TABLE OF zsfi_doc_head.
  DATA: lt_out_temp   TYPE STANDARD TABLE OF zsfi_doc_head_o.
  DATA: lt_item_temp  TYPE STANDARD TABLE OF zsfi_doc_item.
  DATA: ls_parallel   TYPE zsfi_doc_head_run.
  DATA: lt_parallel   TYPE STANDARD TABLE OF zsfi_doc_head_run.
  DATA: gt_out_temp   TYPE STANDARD TABLE OF zsfi_doc_head_o.

  DATA: lv_errcode TYPE char8.
  DATA: lv_errdesc TYPE char250.

* decode the data from the INDX Structure into the process work list
  CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'
    EXPORTING
      indxtab = ct_rfcdata
    IMPORTING
      data    = lt_parallel.



*you own process logic
  LOOP AT lt_parallel INTO ls_parallel.
    CLEAR:lv_errcode,lv_errdesc,lt_item_temp,lt_head_temp,lt_out_temp.


    MOVE-CORRESPONDING ls_parallel TO ls_head_temp.
    APPEND ls_head_temp TO lt_head_temp.

    lt_item_temp = ls_parallel-item.

    CALL FUNCTION 'ZFIFM_RECEIPT_POSTING'
      IMPORTING
        errcode = lv_errcode
        errdesc = lv_errdesc
      TABLES
        it_head = lt_head_temp
        it_item = lt_item_temp
        ot_head = lt_out_temp.

    APPEND LINES OF lt_out_temp TO gt_out_temp.
  ENDLOOP.





* repack output data for AFTER_RFC form
  CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'
    EXPORTING
      data    = lt_parallel
    IMPORTING
      indxtab = ct_rfcdata.
  COMMIT WORK.

ENDFORM.                    "in_rfc
*&---------------------------------------------------------------------*
*&      Form  after_rfc
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->IT_RFCDATA             text
*      -->IF_RFCSUBRC            text
*      -->IF_RFCMSG              text
*      -->IT_OBJECTS_IN_PROCESS  text
*      -->IS_AFTER_RFC_IMP       text
*      -->ES_AFTER_RFC_EXP       text
*      -->CS_USER_PARAM          text
*----------------------------------------------------------------------*
FORM after_rfc USING it_rfcdata  TYPE spta_t_indxtab
                     if_rfcsubrc TYPE sy-subrc
                     if_rfcmsg   TYPE spta_t_rfcmsg
                     it_objects_in_process TYPE spta_t_objects_in_process
                     is_after_rfc_imp      TYPE spta_t_after_rfc_imp
            CHANGING es_after_rfc_exp TYPE spta_t_after_rfc_exp
                     cs_user_param   .
  DATA: lt_out   TYPE STANDARD TABLE OF zsfi_doc_head_o.
  DATA: lt_parallel   TYPE STANDARD TABLE OF zsfi_doc_head_run.
* uppack RFC output data and add RFC reulsts to global data
  CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'
    EXPORTING
      indxtab = it_rfcdata
    IMPORTING
      data    = lt_parallel.

  APPEND LINES OF lt_parallel TO gt_result.

ENDFORM.                    "after_rfc

  上面的demo 我分别使用loop和parallel (10线程)去创建会计凭证

   创建1000条,运行时间分别为:95 sec  17 sec

   如此一比较下来。多线程的效率提升还是很快的。对于没有升级到HANA的ECC 系统还是有很多提升空间的

   

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个 ABAP线程代码示例: REPORT z_multithreading_demo. TYPES: BEGIN OF ty_result, value TYPE i, END OF ty_result. TYPES: ty_result_tab TYPE STANDARD TABLE OF ty_result WITH EMPTY KEY. DATA: gt_input TYPE ty_result_tab, gt_output TYPE ty_result_tab, gv_threads TYPE i VALUE 5. DATA: gr_semaphore TYPE REF TO cl_semaphore, gr_barrier TYPE REF TO cl_barrier. START-OF-SELECTION. PERFORM fill_input_tab. PERFORM create_semaphore. PERFORM create_barrier. PERFORM start_threads. PERFORM print_output_tab. END-OF-SELECTION. *&---------------------------------------------------------------------* *& Form fill_input_tab *&---------------------------------------------------------------------* FORM fill_input_tab. DO 100 TIMES. DATA(ls_input) = VALUE ty_result( value = sy-index ). APPEND ls_input TO gt_input. ENDDO. ENDFORM. *&---------------------------------------------------------------------* *& Form create_semaphore *&---------------------------------------------------------------------* FORM create_semaphore. gr_semaphore = cl_semaphore=>create( initial = gv_threads ). ENDFORM. *&---------------------------------------------------------------------* *& Form create_barrier *&---------------------------------------------------------------------* FORM create_barrier. gr_barrier = cl_barrier=>create( threads = gv_threads ). ENDFORM. *&---------------------------------------------------------------------* *& Form start_threads *&---------------------------------------------------------------------* FORM start_threads. DATA: lt_threads TYPE STANDARD TABLE OF REF TO cl_thread WITH EMPTY KEY. LOOP AT gt_input ASSIGNING FIELD-SYMBOL(<fs_input>). APPEND VALUE #( REF #( cl_thread=>create( iv_mode = cl_thread=>mode_task iv_task = NEW lcl_worker( EXPORTING iv_input = <fs_input> io_output = gt_output ) ) ) ) TO lt_threads. IF lines( lt_threads ) = gv_threads. PERFORM run_threads USING lt_threads CHANGING gr_semaphore. CLEAR lt_threads. ENDIF. ENDLOOP. IF NOT lt_threads IS INITIAL. PERFORM run_threads USING lt_threads CHANGING gr_semaphore. ENDIF. gr_barrier->wait( ). ENDFORM. *&---------------------------------------------------------------------* *& Form run_threads *&---------------------------------------------------------------------* FORM run_threads USING lt_threads CHANGING cr_semaphore TYPE REF TO cl_semaphore. DATA(lv_count) = lines( lt_threads ). DO lv_count TIMES. DATA(lv_rc) = cr_semaphore->request( ). IF lv_rc <> 0. MESSAGE 'Semaphore request failed' TYPE 'E'. ENDIF. ENDDO. DATA: lt_results TYPE ty_result_tab. LOOP AT lt_threads ASSIGNING FIELD-SYMBOL(<fs_thread>). <fs_thread>->start( ). ENDLOOP. DO lv_count TIMES. DATA(lv_rc) = cr_semaphore->release( ). IF lv_rc <> 0. MESSAGE 'Semaphore release failed' TYPE 'E'. ENDIF. ENDDO. LOOP AT lt_threads ASSIGNING FIELD-SYMBOL(<fs_thread>). <fs_thread>->join( ). lt_results = CORRESPONDING #( <fs_thread>->result( ) ) TO lt_results. ENDLOOP. gt_output = CORRESPONDING #( lt_results ). ENDFORM. *&---------------------------------------------------------------------* *& Form print_output_tab *&---------------------------------------------------------------------* FORM print_output_tab. LOOP AT gt_output ASSIGNING FIELD-SYMBOL(<fs_output>). WRITE: / <fs_output>-value. ENDLOOP. ENDFORM. *&---------------------------------------------------------------------* *& Class lcl_worker DEFINITION *&---------------------------------------------------------------------* CLASS lcl_worker DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS: constructor IMPORTING iv_input TYPE ty_result io_output TYPE REF TO ty_result_tab, run. PRIVATE SECTION. DATA: mv_input TYPE ty_result, mo_output TYPE REF TO ty_result_tab. ENDCLASS. *&---------------------------------------------------------------------* *& Class lcl_worker IMPLEMENTATION *&---------------------------------------------------------------------* CLASS lcl_worker IMPLEMENTATION. METHOD constructor. mv_input = iv_input. mo_output = io_output. ENDMETHOD. METHOD run. DATA(ls_result) = VALUE ty_result( value = mv_input-value ). APPEND ls_result TO mo_output. ENDMETHOD. ENDCLASS.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值