V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
qile1
V2EX  ›  Python

threading 线程间通信如何控制线程运行及等待。

  •  
  •   qile1 · Jan 24, 2017 · 3249 views
    This topic created in 3381 days ago, the information mentioned may be changed or developed.

    做一个伸手党。 我写了一个程序检测日志文件变化,如果日志文件新增,我启动一个线程按行读取数据后将内容解析放入数据库,记录行号到.ini 配置文件里面(大约需要 5-10 秒)。由于写入日志程序有时 5 秒内写入多次,导致上个线程还没有执行完,就又启动了一个线程。。。。。。,每个进程执行完写入记录行号时候偶尔会冲突,导致 ini 配置文件最后变为空白 0kb 大小。我想让第一个线程启动之后,再启动的线程等待第一个线程结束后再执行。 我代码部分内容如下:

         t2=threading.Thread(target=runReadLogFile,args=(1,))
        t2.start()#程序启动后先执行一次读取日志文件。
        当检测到日志文件修改后执行:
        t1=threading.Thread(target=runReadLogFile,args=(1,))
        t1.start()
    
    20 replies    2017-01-29 01:47:44 +08:00
    kier
        1
    kier  
       Jan 24, 2017
    直接等线程结束再启动新线程,或者就保持一个线程,定时唤醒
    czheo
        2
    czheo  
       Jan 24, 2017
    you need a lock
    qile1
        3
    qile1  
    OP
       Jan 24, 2017
    @kier 你意思是不是 我在主线程里面定义 线程 1 ,日志文件被修改的时候我启动线程 1

    t2=threading.Thread(target=runReadLogFile,args=(1,))
    t2.start()#程序启动后先执行一次读取日志文件。
    t1=threading.Thread(target=runReadLogFile,args=(1,))#预先设置线程一,等待启动

    当检测到日志文件修改后执行:
    t1.start()#如果 t1 没执行完,再次调用会报错还是继续执行?
    ryd994
        4
    ryd994  
       Jan 24, 2017 via Android
    mahone3297
        5
    mahone3297  
       Jan 24, 2017
    弱弱问下大家:
    * lz 的这种收集日志到 db 的思路,是否 ok ?
    * 为什么不用 logstash ?
    kier
        6
    kier  
       Jan 24, 2017 via iPad
    @qile1 在 runReadLogFile 里去读 log ,处理完后 sleep 一段时间,再尝试去读
    qile1
        7
    qile1  
    OP
       Jan 25, 2017 via Android
    @kier 最开始是这样操作的。
    一个线程循环读文件
    但是到了后期文件大了,加入了日志文件修改检测后处理
    这样后期文件大了。不用平凡读取日志文件。
    latyas
        8
    latyas  
       Jan 25, 2017
    资源访问的临界区请用锁控制
    latyas
        9
    latyas  
       Jan 25, 2017
    或者单写多读,可以去掉锁
    sheep3
        10
    sheep3  
       Jan 25, 2017
    锁,信号量,都行。但个人感觉不是很合理。不说你这个方案本身(也许这是你当前场景的最佳选择),就说如果这个线程必须等上个线程完成后再开始任务,为什么不就开一个线程,循环从队列里面取。
    wjidea
        11
    wjidea  
       Jan 25, 2017
    multiprocessing.Manager()
    manager.Lock()
    kier
        12
    kier  
       Jan 25, 2017
    @qile1 文件大了又怎么样? open 后, seek 到对应位置直接读固定长度的内容,不会有性能问题的!
    另外,不管多少个线程,互斥操作同一个资源都是要顺序执行的,没法并行,所以根本提升不了速度
    qile1
        13
    qile1  
    OP
       Jan 25, 2017 via Android
    @kier 我读取日志文件是一次全部读取,计算行数。如果行数大于 ini 文件的记录值,就按行便利一遍,从记录行开始处理数据(这个操作时间长),日志单行长度不固定,如果从 seek 开始读取固定长度担心出现截取不全。想建立一个队列,里面只有一条,空就加入任务队列,满了就 try 一下捕获异常。
    但是不知道 treading 如何取队列并执行
    kier
        14
    kier  
       Jan 25, 2017
    @qile1 那为什么不直接记录当前读取位置呢?这样下次就可以直接 seek
    q397064399
        15
    q397064399  
       Jan 25, 2017
    加锁吧,没有其它办法
    q397064399
        16
    q397064399  
       Jan 25, 2017
    还有一个简单的办法 申请线程池 然后只有一个线程
    这样可以提交任务到阻塞队列
    xntop
        17
    xntop  
       Jan 25, 2017
    用信号量呗
    qile1
        18
    qile1  
    OP
       Jan 27, 2017 via Android
    发现还是自己不会使用类。还在学习中。
    现在用 queue (1)。
    但是发现日志文件如果是第二天的时候没法从头读取。晚上在学习下
    ryd994
        19
    ryd994  
       Jan 28, 2017
    这个需求为什么用线程?
    多线程访问数据库又不会快
    循环就行

    “再启动的线程等待第一个线程结束后再执行”这样是不对的
    考虑万一你运气不好,一连串的都慢了,就会有一堆在等,然后这个队就没有头了

    加锁,但是不阻塞,拿不到锁就退出,等别人做。
    qile1
        20
    qile1  
    OP
       Jan 29, 2017 via Android
    @ryd994 感觉我可能程序写的有点问题!把读取文件加锁后,如果上一程序在读完日志,开始处理数据插入工作,在有日志增加,检测到锁就退出会导致有数据无法读取到。处理数据这块不好加快速度,得读取具体指值,然后通过多次查询数据库信息比对转换后插入多个表
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5858 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 80ms · UTC 03:08 · PVG 11:08 · LAX 20:08 · JFK 23:08
    ♥ Do have faith in what you're doing.