多线程

作者: abapCiCi | 来源:发表于2021-05-13 10:55 被阅读0次

锁模式

模式E:当更改数据的时候设置为此模式。
模式S:本身不需要更改数据,但是希望显示的数据不被别人更改。
模式X:和E类似,但是不允许累加,完全独占。

多线程

并行RFC(负载均衡)

注意事项

并行RFC调用实际上是异步RFC调用的应用之一
异步RFC调用只适用于多个SAP ABAP系统间的并行处理,不支持SAP系统和其他系统之间

独立的LUW:并行处理不适合需顺序进行的数据处理,并行的数据处理任务必须逻辑上独立于其他任务,各个数据处理过程不能具有依赖关系

被调用的功能模块程序中不能再包含使用目标BACK的远程功能调用(即不能再进行回调)

调用程序不能在异步调用之后生成新的内部会话,即不能在CALL FUNCTION STARTING NEW TASK语句后使用SUBMIT或CALL TRANSACTION语句

不能通过CALL FUNCTION STARTING NEW TASK DESTINATION IN GROUP语句启动外部程序

异步实例

TYPES: BEGIN OF task_type,
  name TYPE string,
  dest TYPE string,
  END OF task_type.

DATA:snd_jobs TYPE i,
      rcv_jobs TYPE i,
      exc_flag TYPE i,
      info TYPE rfcsi,
      mess(80),
      indx(4),
      name(8),
      task_list TYPE STANDARD TABLE OF task_type,
      task_wa TYPE task_type.

DO 9 TIMES.
  indx = sy-index.
  CONCATENATE 'Task' indx INTO name.
  CALL FUNCTION 'RFC_SYSTEM_INFO'
    STARTING NEW TASK name
    DESTINATION IN GROUP DEFAULT
    PERFORMING rfc_info ON END OF TASK
    EXCEPTIONS
      system_failure        = 1  MESSAGE mess
      communication_failure = 2  MESSAGE mess
      resource_failure      = 3  .

  CASE  sy-subrc.
    WHEN 1 OR 2.
      MESSAGE mess TYPE 'I'.
    WHEN 3.
      MESSAGE 'Resource failure ' TYPE 'I'.
  ENDCASE.
ENDDO.

WAIT UNTIL rcv_jobs = 9 UP TO 10 SECONDS.
LOOP AT task_list INTO task_wa.
  WRITE: / task_wa-name,task_wa-dest.
ENDLOOP.

FORM rfc_info USING name.
  task_wa-name = name.
  rcv_jobs = rcv_jobs + 1.
  RECEIVE RESULTS FROM FUNCTION 'RFC_SYSTEM_INFO'
    IMPORTING
      rfcsi_export = info
      EXCEPTIONS
        system_failure = 1 MESSAGE mess
        communication_failure = 2 MESSAGE mess.
  IF sy-subrc = 0.
    task_wa-dest = info-rfcdest.
  ELSE.
    task_wa-dest = mess.
  ENDIF.
  APPEND task_wa TO task_list.
ENDFORM.

上面的程序有问题就是当发生RESOURCE_FAILURE会丢失数据。
需要使用子程序包装递归调用,递归调用前需要wait进程释放,否则程序一致循环,可能会占用太多系统内存,甚至产生system_no_menory错误代码如下。

*&---------------------------------------------------------------------*
*& Report ZTEST_YB_DEMO01
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ztest_yb_demo01.
TYPES: BEGIN OF task_type,
         name TYPE string,
         dest TYPE string,
       END OF task_type.

DATA: snd_jobs  TYPE i,
      rcv_jobs  TYPE i,
      exc_flag  TYPE i,
      ls_time   TYPE i,
      info      TYPE rfcsi,
      mess      TYPE c LENGTH 80,
      indx      TYPE c LENGTH 4,
      name      TYPE c LENGTH 8,
      task_list TYPE STANDARD TABLE OF task_type,
      task_wa   TYPE task_type.
*GET TIME STAMP FIELD DATA(ls_stamp).


DATA:g_taskname(10) TYPE c,                "task name(同时运行的任务名称必须保持唯一)
     g_classname    TYPE rzlli_apcl,          "Server Group Name
     g_applserver   TYPE rzllitab-applserver, "RFC Serve Group
     lv_available   TYPE i,
     lv_total       TYPE i,
     lv_job         TYPE i.


CALL 'C_SAPGPARAM'                                        "#EC CI_CCALL
  ID 'NAME'  FIELD 'rdisp/myname'
  ID 'VALUE' FIELD g_applserver.

SELECT SINGLE classname
  FROM rzllitab
  INTO g_classname   "Server Group Name
  WHERE applserver = g_applserver
  AND grouptype = 'S'.   "S:服务器组,空:登陆组
*  获取 RFC Serve Group name         End--*
CALL FUNCTION 'SPBT_INITIALIZE'
  EXPORTING
    group_name                     = g_classname
  IMPORTING
    max_pbt_wps                    = lv_total
    free_pbt_wps                   = lv_available
  EXCEPTIONS
    invalid_group_name             = 1
    internal_error                 = 2
    pbt_env_already_initialized    = 3
    currently_no_resources_avail   = 4
    no_pbt_resources_found         = 5
    cant_init_different_pbt_groups = 6
    OTHERS                         = 7.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

GET RUN TIME FIELD ls_time.
DO 200 TIMES.
  indx = sy-index.
  CONCATENATE 'Task' indx INTO name.
  PERFORM frm_parallel_task USING name.
ENDDO.
WAIT UNTIL rcv_jobs GE snd_jobs .
*GET TIME STAMP FIELD DATA(ls_stamp1).
GET RUN TIME FIELD ls_time.
ls_time = ls_time / 1000000.
WRITE:/ `运行时间` && ls_time.
LOOP AT task_list INTO task_wa.
  WRITE: / task_wa-name, ', Server:', task_wa-dest.
ENDLOOP.

FORM rfc_info USING name.
  task_wa-name = name.
  rcv_jobs = rcv_jobs + 1.
  RECEIVE RESULTS FROM FUNCTION 'RFC_SYSTEM_INFO'
  IMPORTING
    rfcsi_export = info
  EXCEPTIONS
    system_failure        = 1 MESSAGE mess
    communication_failure = 2 MESSAGE mess.

  IF sy-subrc = 0.
    task_wa-dest = info-rfcdest.
  ELSE.
    task_wa-dest = mess.
  ENDIF.
  APPEND task_wa TO task_list.
  CLEAR  task_wa.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_PARALLEL_TASK
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*      -->P_NAME  text
*&---------------------------------------------------------------------*
FORM frm_parallel_task  USING    p_name.
  CALL FUNCTION 'RFC_SYSTEM_INFO'
    STARTING NEW TASK name
*    DESTINATION IN GROUP DEFAULT "g_classname  "' 390' "pRFC
    DESTINATION 'NONE'
    PERFORMING rfc_info ON END OF TASK
    EXCEPTIONS
      system_failure        = 1 MESSAGE mess
      communication_failure = 2 MESSAGE mess
      resource_failure      = 3.

  CASE sy-subrc.
    WHEN 0.
*      WAIT UP TO 1 SECONDS.
      snd_jobs = snd_jobs + 1.
    WHEN 1 OR 2.
      MESSAGE mess TYPE 'I'.
    WHEN 3.
      WAIT UP TO '0.1' SECONDS.
      PERFORM frm_parallel_task USING p_name.
    WHEN OTHERS.
      MESSAGE 'Other error' TYPE 'I'.
      RETURN.
  ENDCASE.
ENDFORM.

来自引用

1、DIALOG程序获得用户要更新的数据,并把它写到一个特殊的LOG TABLE,表内的条目属于同一个请求类型,包含了稍后将要写到数据库的数据。一个DIALOG程序可以写多条数据到LOG TABLE。写进LOG TABLE里的条目属于同一个LUW,意思就是它们要么都被执行,要么都不被执行。
2、DIALOG程序关闭LUW(将LOG TABLE的条目打包),并通知系统基本程序有一个包的数据需要更新。
3、系统基本程序从LOG TABLE读取这个LUW的需要更新的数据,并把这些数据提供给系统更新程序。
4、系统更新程序接受传输给它的数据,并更新数据库。
5、如果更新程序运行成功,系统基本程序删除这个LUW在LOG TABLE的所有数据;如果失败,保持LOG TABLE的这些数据,并标记不成功。触发更新程序的用户会收到系统发的关于这个错误的E-MAIL。可以用参数rdisp/vbmail(1发,0不发)来控制错误时是否发E-MAIL和rdisp/vb_mail_user_list($ACTUSER代表创建更新数据的用户)来控制错误时发E-MAIL给谁。可以用事务SM13来监控更新请求。

在DIALOG程序中,通过一个特别的FM,使用IN UPDATE TASK。如:
CALL FUNCTON 'F1' IN UPDATE TASK
EXPORTING
P1 = A
P2 = B.
使用这样写法的FM不会立即执行,而是写进LOG TABLE,作为一个执行请求,一个SAP LUW下的更新请求存储在同一个UPDATE KEY下。对一个SAP LUW来说UPDATE KEY是一个唯一的世界范围的识别码,意思就是一个SAP LUW的UPDATE KEY是唯一的,不会和另外的SAP LUW的UPDATE KEY重复。
只有当程序执行到COMMIT WORK的时候,才会为这些请求创建一个抬头条目LOG HEADER,表示以上这些同样UPDATE KEY的属于同一个包,然后系统关闭这个LUW。当LOG HEADER创建以后,系统通知DISPATCHER有一个更新包已经准备好可以处理了。

相关文章

  • iOS多线程 NSOperation

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程 pthread、NSThread

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程: GCD

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程运用

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • iOS多线程基础

    系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线...

  • 多线程介绍

    一、进程与线程 进程介绍 线程介绍 线程的串行 二、多线程 多线程介绍 多线程原理 多线程的优缺点 多线程优点: ...

  • iOS进阶之多线程管理(GCD、RunLoop、pthread、

    深入理解RunLoopiOS多线程--彻底学会多线程之『GCD』iOS多线程--彻底学会多线程之『pthread、...

  • iOS多线程相关面试题

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程之--NSOperation

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS多线程之--NSThread

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

网友评论

      本文标题:多线程

      本文链接:https://www.haomeiwen.com/subject/ykmtjltx.html