ABAP优化降低时间复杂度多线程运行的基本方法

ABAP多线程程序运行              

Author: Chaim Wang

Date: 2018/7/19

 

在ABAP中,有时因为数据量过大可能会影响用户的体验度,导出一点数据有时都会等上半个小时,为了避免这种情况,在此引用大数据的基本原理并行执行数据。减少系统运行的时间,就必须要牺牲内存或者CPU的,这里只仅仅是说明如何牺牲CPU提高程序运行速度在ABAP的执行方式。

如上图所示若将一个程序的作业量平均分成两份,则运行的时间将变成原来的一半。以此类推在扩展,数据查询时间将以成倍减少。

  1. SUBMIT的运用

Submit在ABAP中调用其他程序的方式,(比如我们现在正在运行A程序,但是中间需要B程序运行并给我们返回数据,一般的方式我们都会直接复制B程序到A程序然后在执行)。其实submit可以很容易的传入输入参数返回输出参数在内存。关于使用方法可以参考网络或一下代码

FIELD-SYMBOLS<Itab> TYPE data.
FIELD-SYMBOLS:<lt_data>  TYPE ANY TABLE,
              <lt_data_line>  TYPE ANY TABLE.
DATA:         lr_data               TYPE REF TO data,
              lr_data_line TYPE REF TO data.
DATA:         lr_data_descr          TYPE REF TO cl_abap_datadescr,
              lr_data_descr_line TYPE REF TO cl_abap_datadescr.
DATA:FLAG TYPE C VALUE ''.

DATAlt_selscreen LIKE rsparams OCCURS 0.
DATAwa_selscreen LIKE LINE OF lt_selscreen.

CLEAR:flag"flag初始化
         cl_salv_bs_runtime_info=>set(
          EXPORTING display  abap_false
                        metadata 
abap_false
                        
data     abap_true ).
*         Submit standard program with selection table
       SUBMIT ZPPR0008 WITH SELECTION-TABLE lt_selscreen "
                          WITH p_werks WERK_TAB-WERKSA
          
AND RETURN.
        TRY."MB51ALV输出有headerlist 所以要有2个参数
            cl_salv_bs_runtime_info=>get_data_ref(
                 IMPORTING r_data_descr      lr_data_descr ).
                        "   r_data_line_descr = lr_data_descr_line
            IF lr_data_descr IS NOT INITIAL .
              CREATE DATA lr_data TYPE HANDLE lr_data_descr.
         "   CREATE DATA lr_data_line TYPE HANDLE lr_data_descr_line.
            ASSIGN lr_data->TO <lt_data>.
         "   ASSIGN lr_data_line->* TO <lt_data_line>.
            cl_salv_bs_runtime_info=>get_data(
              IMPORTING
                t_data      =      <lt_data>
           
"     t_data_line      =      <lt_data_line>
                   ).
            ELSE.
             "  MESSAGE '讯息:没有符合您设定的范围数据!!' TYPE 'E'.
                flag 'X'.
            ENDIF.
          CATCH cx_salv_bs_sc_runtime_info.
          "  MESSAGE `Unable to retrieve ALV data` TYPE 'E'.
            flag 'X'.
        ENDTRY.
        cl_salv_bs_runtime_info=>clear_all( ).
      IF flag ''.
        LOOP AT <lt_data> ASSIGNING <Itab>.
              MOVE-CORRESPONDING <Itab> to IT_ITAB.
              APPEND IT_ITAB.
              CLEAR IT_ITAB.
        ENDLOOP.
      ENDIF.

FORM SHUJU TABLES Tab  USING A.
FIELD-SYMBOLS<Itab1> TYPE data.
LOOP AT Tab ASSIGNING <Itab1>.
  MOVE-CORRESPONDING <Itab1> to wa_selscreen.
  wa_selscreen-selname A.
  wa_selscreen-kind 'S'.
APPEND wa_selscreen TO lt_selscreen.
CLEARwa_selscreen.
ENDLOOP.
ENDFORM.

以上是SUBMIT的处理方法,但是不足的是这个也是串行运行程序,程序运行在此处时会等待返回结果后才继续运行下去。

  1. 后台运行

其实submit可以使用后台运行,但是数据不能通过内存传输过来,运行完毕后就丢失了,所以这是我们要关注的解决的主要问题点,如果我们想想在ABAP中启动这个后台运行程序,将结果的数据在传入我们此时正在运行的程序,那么程序可以按倍数的降低运行时间。

DATAJOBCOUNT LIKE TBTCJOB-JOBCOUNT,
      HOST LIKE MSXXLIST-HOST.
DATABEGIN OF STARTTIME.
        INCLUDE STRUCTURE TBTCSTRT.
DATAEND OF STARTTIME.
DATASTARTTIMEIMMEDIATE LIKE BTCH0000-CHAR1 VALUE 'X'.
DATAactual_status LIKE TBTCJOB-STATUS .
DATA e_return TYPE INT4.
DATA e_message TYPE CHAR40.
DATA joblogtbl LIKE RANGE OF TBTC5 WITH HEADER LINE.
DATAJOBNAME LIKE TBTCJOB-JOBNAME.

“开始启动后台运行的方式。

CONCATENATE 'ZM08' SY-DATUM SY-UZEIT SY-UNAME INTO JOBNAME.
PERFORM JOB_OPEN CHANGING JOBNAME JOBCOUNT.
SUBMIT Z_YOUHUA_ZM08_2  WITH SELECTION-TABLE lt_selscreen
                        
WITH JOBNAME  =  JOBNAME
AND RETURN
                        USER SY-UNAME
                        VIA JOB JOBNAME
                        
NUMBER JOBCOUNT.
IF SY-SUBRC > 0.
     EXIT.
ENDIF.
PERFORM JOB_CLOSE USING JOBNAME JOBCOUNT.

放入A程序运行的程序

A程序运行结束后或者需要B程序的返回数据时

PERFORM JOB_CHECKSTATE USING jobname jobcount.

 

FORM JOB_OPEN CHANGING JOBNAME JOBCOUNT.
  CALL FUNCTION 'JOB_OPEN'
  EXPORTING
    DELANFREP        ' '
    JOBGROUP         ' '
    JOBNAME          JOBNAME
    SDLSTRTDT        
SY-DATUM
    SDLSTRTTM        
SY-UZEIT
  
IMPORTING
    JOBCOUNT         JOBCOUNT
  
EXCEPTIONS
    CANT_CREATE_JOB  01
    INVALID_JOB_DATA 02
    JOBNAME_MISSING  03.

IF SY-SUBRC NE 0.
   EXIT.
ENDIF.
ENDFORM.

FORM JOB_CLOSE USING JOBNAME JOBCOUNT.
CALL FUNCTION 'JOB_CLOSE'
  EXPORTING
    EVENT_ID             STARTTIME-EVENTID
    EVENT_PARAM          
STARTTIME-EVENTPARM
    EVENT_PERIODIC       
STARTTIME-PERIODIC
    JOBCOUNT             
JOBCOUNT
    JOBNAME              
JOBNAME
*    LASTSTRTDT           = STARTTIME-LASTSTRTDT
*    LASTSTRTTM           = STARTTIME-LASTSTRTTM
    PRDDAYS              0                    "周期执行
    PRDHOURS             0
    PRDMINS              0
    PRDMONTHS            0
    PRDWEEKS             0
*    SDLSTRTDT            = STARTTIME-SDLSTRTDT
*    SDLSTRTTM            = STARTTIME-SDLSTRTTM  "执行最后期限
    STRTIMMED            STARTTIMEIMMEDIATE    "立刻执行
    TARGETSYSTEM         HOST
  
EXCEPTIONS
    CANT_START_IMMEDIATE 01
    INVALID_STARTDATE    02
    JOBNAME_MISSING      03
    JOB_CLOSE_FAILED     04
    JOB_NOSTEPS          05
    JOB_NOTEX            06
    LOCK_FAILED          07
    OTHERS               99.

IF SY-SUBRC EQ 0.
  "error processing
ENDIF.
ENDFORM.

检测后台运行状态。
FORM JOB_CHECKSTATE USING jobname jobcount.
           CALL FUNCTION 'BP_JOB_CHECKSTATE'
            EXPORTING
              dialog                       'N'
              jobcount                     jobcount
              jobname                      
jobname
            
IMPORTING
              actual_status                actual_status
            
EXCEPTIONS
              checking_of_job_has_failed   1
              correcting_job_status_failed 2
              invalid_dialog_type          3
              job_does_not_exist           4
              no_check_privilege_given     5
              ready_switch_too_dangerous   6
              OTHERS                       7.
          IF sy-subrc <> 0.
            e_return 8.  "JOBSTATUS取得失敗
            e_message text-008.
            RETURN.
          ENDIF.
          IF actual_status 'F' )
            OR actual_status 'A' ).
            RETURN.
          ENDIF.
     DO 7200 TIMES.
          WAIT UP TO SECONDS.
          CALL FUNCTION 'BP_JOB_CHECKSTATE'
            EXPORTING
              dialog                       'N'
              jobcount                     jobcount
              jobname                      
jobname
            
IMPORTING
              actual_status                actual_status
            
EXCEPTIONS
              checking_of_job_has_failed   1
              correcting_job_status_failed 2
              invalid_dialog_type          3
              job_does_not_exist           4
              no_check_privilege_given     5
              ready_switch_too_dangerous   6
              OTHERS                       7.
          IF sy-subrc <> 0.
            e_return 8.  "JOBSTATUS取得失敗
            e_message text-008.
            EXIT.
          ENDIF.
          IF actual_status 'F' )
            OR actual_status 'A' ).
            EXIT.
          ENDIF.
    ENDDO.
 ENDFORM.

 

3、为了避免相同程序重复运行产生的后台任务冲突,我们可以将作业名取名为用户加当前日期时间,用户不可能在同一时间开启两个相同任务运行。就算两个窗口,点击执行也有时间差,所以此问题就可以很好的避免了。

4、程序的后台运行我们已经启动了,现在关键是如何获取B程序运行的数据。

其实这里是将B运行的数据存入数据表里,再在A程序的数据表里数据查找出来,并删除数据表。建立数据表要注意一下条件。

(1)、防止多个程序的运行,数据表传入数据,或写入数据的混乱。

(2)、当有意外情况数据表里的数据未能删除,列入程序运行一般退出了。

(3)、当一个程序有多个数据表传输数据,可以用全用一个表来满足数据的传输。

所以首先我们要以作业名字为关键字。这样可以解决多个应用程序运行互不干扰,在以一个程序的标识作为关键字以防止多个表的数据传输在一个表里互不干扰,最后在一个序号作为关键字,以表示每个表数据记录的真实性。为了防止第二中情况的发生可以在数据表里加入日期,当数据表在新的一天运行的时候发现数据表里有数据,可以先进行删除不是这一天和上一天的数据。此可避免异常产生的数据的永久存放数据表。

图3 关键字数据表

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值