阿里狗去死吧

希望那出題狗?能看到,面試題沒必要這麼HY coder吧

  1. 題目:

    
    ```sql
    CREATE TABLE `student` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(250) DEFAULT '1' COMMENT '名字',
      `teacher_id` int(11) DEFAULT '0' COMMENT '老師id'
    ) ENGINE=InnoDB CHARSET=utf8 COMMENT='學生表';
    
    CREATE TABLE `teacher` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(250) DEFAULT '1' COMMENT '名字',
      `check_time` datetime NOT NULL COMMENT '打卡時間'
    ) ENGINE=InnoDB CHARSET=utf8 COMMENT='老師表'
    ```
    
    用python語言, 寫一個"老師"進程, 要求:
    1. 進程啓動時, 會往teacher表裏面插入一條記錄, 記下這條記錄的id值, 保存爲t_id. 
    2. 進程定期更新其t_id對應記錄的"check_time"字段.
    3. 進程定期掃描student表, 如果有teacher_id爲0的記錄, 將該字段更新爲其t_id.
    4. 當啓動兩個進程A和B時, 這兩個進程可以平分所有的student, 即一半student的teacher_id爲進程A的t_id, 另一半student的teacher_id爲進程B的t_id.
    5. 再啓動一個進程C的時候, 1/3的student的teacher_id爲進程A的t_id, 1/3爲歸進程B, 1/3歸進程C.
    6. 當進程A因爲各種原因掛了, 不再更新check_time字段時, 進程B和進程C可以瓜分進程A託管的學生.
    
  2. 我寫的答案:

    import multiprocessing
    from pymysql import *
    import datetime
    import threading
    import time
    import os
    
    
    class MyMysql(object):
        """
        進程類
        """
    
        def __init__(self):
            self.row_range = ""  # 掃面的工作範圍元組類型
            self.con = connect(
                host='localhost',
                port=3306,
                database='ceshi',
                user='root',
                password='mysql',
                charset='utf8')
            self.cs = self.con.cursor()
            self.time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            self.t_id = ""
            self.q = ""  # todo 這裏留一個通訊隊列
            self.q1 = ""  # 線程運行數量隊列
    
        def mysql_init(self):
            """
            # 1. 進程啓動時, 會往teacher表裏面插入一條記錄, 記下這條記錄的id值, 保存爲t_id.
            :return: 返回值是t_id
            """
            self.cs.execute("""insert into teacher(check_time) \
                    values(str_to_date(\'%s\','%%Y-%%m-%%d %%H:%%i:%%s'));""" % self.time)
            self.cs.execute("""SELECT LAST_INSERT_ID()""")
            self.t_id = self.cs.fetchone()[0]
    
        def update_teacher(self):
            """
            # 2. 進程定期更新其t_id對應記錄的"check_time"字段. --實現
            :return:
            """
            while True:
                print("update ok")
                time.sleep(3)
                self.time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                self.cs.execute("""update teacher set \
                        check_time=str_to_date(\'%s\','%%Y-%%m-%%d %%H:%%i:%%s') where id=%d;""" % (self.time, self.t_id))
                self.con.commit()
    
        def up_stu_tid(self):
            """
            # 3. 進程定期掃描student表, 如果有teacher_id爲0的記錄, 將該字段更新爲其t_id.
            # 4. 當啓動兩個進程A和B時, 這兩個進程可以平分所有的student, 即一半student的teacher_id爲進程A的t_id,
            #    另一半student的teacher_id爲進程B的t_id。
            # 5. 再啓動一個進程C的時候, 1/3的student的teacher_id爲進程A的t_id, 1/3爲歸進程B, 1/3歸進程C.
    
            :return:
            """
            while True:
                time.sleep(5)
                self.cs.execute(
                    """select id from student where teacher_id=0 limit %d,%d;""" %
                    self.row_range)
                a = self.cs.fetchall()
                for i in a:
                    self.cs.execute(
                        """update student set teacher_id=%s where id= %s""" %
                        (self.t_id, i[0]))
    
        def tell_mian_live(self):
            """
            告訴主進程我還活着 和 進程 id
            此函數要定期執行
            :return:
            """
            time.sleep(1)  # 每兩秒執行一次,進行函數的使用
            self.q.put(os.getpid())  # 將子進程號放到隊列中
    
        def get_p_live(self):
            """
            更改全局變量
            :return:
            """
            while True:
                try:
                    self.row_range = self.q1.get()
                except Exception as e:
                    print(e)
    
        def my_pro_run(self, range_r, q, q1):
            """
            總的運行程序
            :return:
            """
            self.q = q  # 重置進程隊列
            self.q1 = q1
            self.row_range = range_r
            print(self.row_range)
            self.mysql_init()
            print(self.t_id, type(self.t_id))
            # todo 開啓定時報告存活 功能
            threading.Thread(target=self.tell_mian_live).start()
            threading.Thread(target=self.update_teacher).start()
            threading.Thread(target=self.up_stu_tid).start()
            self.con.commit()
    
    
    class JinCheng(object):
        def __init__(self, fun, num):
            self.conn = connect(
                host='localhost',
                port=3306,
                database='ceshi',
                user='root',
                password='mysql',
                charset='utf8')
            self.cs2 = self.conn.cursor()
            self.cs2.execute("select count(*) from teacher;")
            self.mysql_row = self.cs2.fetchall()[0][0]  # 數據中的行數
            self.pro_list = [fun] * num
            self.pro_arg = ""
            self.q = multiprocessing.Queue()  # todo 進程通訊工具
            self.q1 = multiprocessing.Queue()  # todo 進程通訊工具
            self.chang_num_pro = 0
    
        def start_pro(self):
            for i in self.pro_list:
                time.sleep(0.02)  # 延遲0.02 秒 生成文件
                multiprocessing.Process(target=i, args=(
                    (self.pro_arg[0][len(self.pro_list) - 1], self.pro_arg[1]), self.q, self.q1)
                                        ).start()
                print(" 開啓成功")
    
        def cha_xu(self, a, b):
            """
            :param a: 數據庫行數
            :param b: 進程數
            :return: 步進值和點值 -》 第幾個進程 號-1  加步長
            """
            step_int = a // len(self.pro_list)
            if step_int % 2 == 0:
                step = round(a / b) + 1
            else:
                step = round(a / b)
            limit_page = []
            for i in range(0, a, step):
                limit_page.append(i)
    
            self.pro_arg = (limit_page, step)
            print(self.pro_arg)
    
        def check_pro(self):
            """
            判斷開啓的進程和進程列表中的數量是不是相同
            此函數單獨開工線程使用
            :return:
            """
            start_pro = len(self.pro_list)
            print("start_pro", start_pro)
    
            def q_getpid(start_pro):
                get_q = []  # 進程號列表
                for i in range(start_pro):
                    try:
                        count = self.q.get()
                        if count in get_q:
                            pass
                        else:
                            get_q.append(count)
                    except Exception as e:
                        print(e)
                return get_q
            while True:
                a = q_getpid(start_pro)
                b = q_getpid(start_pro)
                if a == b:
                    pass
                else:
                    for i in a:
                        if i in b:
                            pass
                        else:
                            print("死掉的進程", i)
                            start_pro -= 1  # 進程數減少1
                            self.chang_num_pro = start_pro
                            self.cha_xu(self.mysql_row, self.chang_num_pro)
                            self.q1.put(self.pro_arg)  # 將更改後的參數發送給子進程
    
        def run_pro(self):
            """
            運行初始化
            :return:
            """
    
            self.cha_xu(self.mysql_row, len(self.pro_list))
            self.start_pro()
            threading.Thread(target=self.check_pro).start()
    
    
    if __name__ == '__main__':
    
        a = MyMysql()
        jin = JinCheng(a.my_pro_run, 3)
        jin.run_pro()
    
  3. 微信
    在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章