• app自动化11 线程实现多个脚本在多个手机运行


    线程

    多任务简单介绍

    - 有很多事情在现实生活的场景中是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的。
    - 多任务,就是能够在同一时间同时进行多个任务。
    这样同时进行多个任务,有一个极大的好处,那就是节省时间
    代码举例
    import time
    import threading
    
    def sing():
        for i in range(5):
            print("唱歌")
            time.sleep(1)
    
    def dance():
        for i in range(5):
            print("跳舞")
            time.sleep(1)
    
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    
    t1.start()
    t2.start()
    import time
    import threading
    
    def sing():
        for i in range(5):
            print("唱歌")
            time.sleep(1)
    
    def dance():
        for i in range(5):
            print("跳舞")
            time.sleep(1)
    
    sing()
    dance()
    第一段代码开启3个线程,分别是主线程,子线程t1,子线程t2,耗时一共是5秒
    第二段代码开启1个线程,那就是主线程,耗时一共是10秒

    为什么第一段代码耗时只要5秒,而第二段代码耗时要10秒呢?

    下面就由sunt来为大家说下原因吧,先分析第一段代码:
    主线程先开始运行,然后让两个小弟,也就是子线程t1,t2。分别去执行sing()和dance()代码,这两个小弟是并行执行的,并不是说小弟t1先执行完,
    小弟t2才去执行,而是两个小弟同时执行,故耗时为5秒,图解如下:
    打印出来结果:
    唱歌
    跳舞
    跳舞
    唱歌
    跳舞
    唱歌
    跳舞
    唱歌
    跳舞
    唱歌
    这是因为当他们从休眠到唤醒是同时的,故资源掠夺的不确定性,有可能跳舞先执行,也有可能唱歌先执行,不过一定是成对出现的。
    并行执行耗时总时间为5秒。

    接下来分析第二段代码:
    主线程先开始执行,然后主线程执行sing()代码块,等待sing()代码块执行完之后,才开始执行dance()代码块。故耗时为sing()代码块
    的时间加dance()代码块的时间,一共为10秒。图解如下:

    多任务的原理

    什么叫“多任务”呢?简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。
    单核cpu工作原理
    - 现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?
    - 答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。实际上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。
    - 真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。
    多核cpu工作原理
    和单核类似,相当于多了一个干活的人。
    并发:指的是任务数多于cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行
    (实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
    并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的
    - 并行和并发都算是多任务,但并行实际上才是真正的多任务,并发是假的。

    线程的两张创建方式

    - 直接使用threading模块的Thread类,指定要执行的方法,再调用start
    - 使用继承的方式,继承Thread类,重新run方法,创建这个对象后,再调用start

    查看当前程序线程数量

    threading.enumerate()
    - 获取所有线程,返回的是一个列表。
    - 如果需要个数,使用len(threading.enumerate())

    为子线程传递参数

    target方式
    import time
    import threading 
    
    def sing(nums):
        for i in range(nums):
            print("唱歌")
            time.sleep(1)
    
    def dance():
        for i in range(5):
            print("跳舞")
            time.sleep(1)
    
    t1 = threading.Thread(target=sing, args=(3,))
    t2 = threading.Thread(target=dance)
    
    t1.start()
    t2.start()
    类继承方式
    import threading
    
    class Work1(threading.Thread):
    
        def __init__(self, nums):
            super().__init__()
            self.nums = nums
    
        def run(self):
            for i in range(self.nums):
                print("haha")
    
    
    def main():
        w = Work1(2)
        w.start()
    
    if __name__ == "__main__":
        main()

    Appium多端口

    目标,让一个脚本去跑到多台手机。
    注意点: appium sever端口要不同,开启多个。bootstrap端口要不同,开启多个。udid需要指定,udid表示设备的唯一表示符号,通过 adb devices 查看。 前半部分都是,比如模拟器的(192.168.57.101:5555)。
    appium server  和  bootstrap 和 udid 应该是成对出现的。
    命令:
    appium -p 4723 -bp 4724 -U 192.168.57.101:5555
    -p 表示 appium的端口
    -bp 表示 bootstrap的端口
    -U 表示设备的标识符
    修改init_driver让,init_driver接受port的参数。并且进行对应的连接。
    记得,创建的是不同的driver对象。
    因为如果使用threading.Thread的这种形式,需要指定执行的函数,所以,把需要执行的代码,封装成一个函数。然后使用
        ports = ["4723", "4725"]
    
        for i in ports:
            threading.Thread(target=do, args=(i,)).start()
    来去执行创建多个driver并且进行脚本的操作。
    下面看图解就知道appium多端口的工作原理了。
    依照上图可以知道,如果要想让一段脚本操作两个手机,那么我要做的就是,开启两个appium服务和两个bootstrap服务,并且端口号不能相同,
    appium和bootstrap是一对,并且有两个手机,还要指定手机设备号,故命令如下
    appium -p 4723 -bp 4724 -U 192.168.57.101:5555
        
    appium -p 4725 -bp 4726 -U 192.168.57.102:5555

    代码实现

    命令行先启动appium并指定端口,并指定bootstrap端口和手机设备号
    appium -p 4723 -bp 4724 -U 192.168.57.101:5555
        
    appium -p 4725 -bp 4726 -U 192.168.57.102:5555
    base_driver.py
    from appium import webdriver
    
    
    def init_driver(port="4723"):
        # server 启动参数
        desired_caps = dict()
        # 设备信息
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '5.1'
        desired_caps['deviceName'] = '192.168.164.101:5555'
        # app信息
        desired_caps['appPackage'] = 'com.android.settings'
        desired_caps['appActivity'] = '.Settings'
        # 中文
        desired_caps['unicodeKeyboard'] = True
        desired_caps['resetKeyboard'] = True
        # 不重置应用
        desired_caps['noReset'] = True
        # toast
        # desired_caps['automationName'] = 'Uiautomator2'
        # 声明对象
        driver = webdriver.Remote('http://localhost:' + port + '/wd/hub', desired_caps)
        return driver
    login_page.py
    from base_action import BaseAction
    
    
    class LoginPage(BaseAction):
    
        pass
    demo.py
    import threading
    
    from selenium.webdriver.common.by import By
    
    from base_driver import init_driver
    from base_action import BaseAction
    from login_page import LoginPage
    
    
    def do(port):
        driver = init_driver(port)
        login_page = LoginPage(driver)
        if "4723" == port:
            login_page.click((By.XPATH, "text,更多"))
        else:
            login_page.click((By.XPATH, "text,WLA"))
    
    def main():
        //根据ports不同,driver可以连接不同的手机
        ports = ["4723", "4725"]
    
        for i in ports:
            threading.Thread(target=do, args=(i,)).start()
    
    if __name__ == '__main__':
        main()
    
  • 相关阅读:
    代理模式
    建造者模式
    开源版本 hadoop-2.7.5 + apache-hive-2.1.1 + spark-2.3.0-bin-hadoop2.7整合使用
    Phoenix映射HBase数据表
    使用sqoop将mysql中表导入hive中报错
    数据库索引原理及优化(转载)
    6.JAVA知识点归纳整理
    5.hbase表新增数据同步之add_peer
    mongodb分布式集群搭建
    4.HBASE数据迁移方案(之snapshot):
  • 原文地址:https://www.cnblogs.com/st998/p/13808117.html
Copyright © 2020-2023  润新知