多线程 - 为何python子线程会等待很长时间
高洛峰
高洛峰 2017-04-18 09:32:14
0
2
666

背景:运行一个爬虫,开了10个线程,每个线程先去爬取指定数量的代理作为自己的代理池,然后开始工作。

问题:下面是爬虫日志的两行,可以看到在第一行任务处等待了45秒,而这里不过是输出一条信息,十分不理解为什么等了这么长时间?日志中像这样动辄十几秒什么一两分钟的情形基本都发生在爬取代理的过程中,是否意味着这个任务的代码有问题?

15:57:50    INFO    Thread-2    the proxy already in list, skip
15:58:35    INFO    Thread-10       {'https': '117.170.28.178:8123'} download 2111 bytes in 0.75 seconds(average in 1 tries), need 10, available count: 7    

思考:我理解python的多线程调度机制是完成了一条指令后,就可以调用其他线程了,并不是一定要等着这个指令得到了预期的结果,那么如果我的代码写的有问题也不至于影响他的调度吧。这个线程没有进展又不将CPU的使用权让渡出来,GIL为什么不剥夺这个线程的运行时间,总不至于是在等待某个程序块或者函数运行完毕吧。

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

모든 응답(2)
小葫芦

설명된 문제는 주로 SQLite의 부적절한 사용으로 인해 발생하는 것으로 나타났습니다. 이전 설계에서는 에이전트 풀에 있는 모든 에이전트의 확인이 완료될 때까지 연결을 열고 특정 수의 에이전트가 캡처된 후 종료하도록 되어 있었습니다. 접속할 때마다 에이전트 정보를 추가, 수정, 삭제할 때마다 데이터 파일이 작성되어 조잡한 SQLite가 오랫동안 잠기는 현상이 발생합니다.

이 문제를 발견한 후, 새로운 연결이 시작될 때 인벤토리 에이전트를 읽은 후 즉시 연결을 닫았습니다. 이후 모든 에이전트 신규, 업데이트 및 삭제된 데이터는 클래스 변수에 임시 저장됩니다. 필요한 모든 에이전트를 얻은 다음 새 연결을 열고, Executemany를 사용하여 데이터를 업데이트한 다음 연결을 닫고 예약된 작업을 완료하면 속도가 빨라집니다.

그러나 원래 상황에서 스레드 예약 메커니즘이 데이터베이스에 의해 차단된 스레드가 시간에 맞춰 전환하는 대신 항상 리소스를 점유하도록 허용하는 이유를 여전히 이해할 수 없습니다.

伊谢尔伦

따라서 스레드가 데이터베이스 쓰기 수준에서 차단되었습니다. sqlite을 사용하고 있으므로 데이터베이스 쓰기 작업 속도를 높이는 또 다른 고대 기능을 제공하겠습니다.

으아악

sqlite쓰기 속도

속도를 높이는 세 가지 방법이 사용됩니다.
  1. 디스크 동기화 끄기

  2. SQLite 트랜잭션

  3. 많은 일괄 삽입 실행

PS: 또한 메모리가 충분하다면 데이터베이스 파일을 tmpfs 디렉터리에 넣을 수 있습니다. 그러면 디스크 I/O의 영향이 크게 줄어듭니다(메모리에 직접 쓰는 것과 동일).

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!