如何在Python中创建线程安全的单例模式
我想在我的Django应用程序中保持线程的运行。因为我不能在模型或者会话中做到这一点,所以我想到了使用单例模式来保存它们。我研究了这个一段时间,但还没有找到一个好的教程来实现这个。
有没有人知道怎么在Python中创建一个线程安全的单例?
编辑:
更具体来说,我想实现一种“随时算法”,也就是说,当用户按下一个按钮时,应用会立即返回一个响应,并开始一个新的计算(也就是一个新线程)。我希望这个线程一直运行,直到用户再次按下按钮,然后我的应用会返回它找到的最佳解决方案。为此,我需要在某个地方保存这个线程对象——我想到了把它存储在会话中,但显然我不能这样做。
总之,我有一个复杂的计算想在服务器端进行,使用不同的线程,同时用户在使用我的网站。
2 个回答
如果你想在网页应用中使用异步代码,那你可能走错了方向。你应该使用像Celery这样的专门任务队列来处理后台任务:http://celeryproject.org/
你面临的最大问题是网页服务器的架构。除非你不按照推荐的Django网页服务器配置去做,并使用工作线程的MPM,否则你将无法在请求之间跟踪线程的处理,因为每个请求通常会占用自己的进程。这就是Apache的正常工作方式:http://httpd.apache.org/docs/2.0/mod/prefork.html
编辑:
根据你的编辑,我觉得你可以通过创建一个自定义解决方案来学到更多,具体可以这样做:
- 在数据库中维护开始/停止的状态
- 创建一个作为守护进程运行的新程序
- 定期检查开始/停止的状态,并在这里开始或结束工作
在这里不需要多线程,除非你需要为每个用户创建一个新进程。如果是这样,事情会变得更复杂,使用Celery会让你的生活轻松很多。
除非你有非常好的理由,否则你应该在一个完全不同的进程中执行那些运行时间很长的线程,并使用Celery来执行它们:
Celery是一个开源的异步任务队列/作业队列,基于分布式消息传递。它主要用于实时操作,但也支持定时任务。
执行单元被称为任务,这些任务可以在一个或多个工作节点上同时执行,使用多进程、Eventlet或gevent。任务可以异步执行(在后台运行)或同步执行(等到准备好再执行)。
给Django开发者的Celery指南:http://django-celery.readthedocs.org/en/latest/getting-started/first-steps-with-django.html
关于单例和在任务/线程之间共享数据,除非你有好的理由,否则你应该谨慎使用数据库层(也就是模型),并注意数据库锁和更新过期数据的问题。
更新:关于你的使用场景,定义一个Computation
模型,里面有一个status
字段。当用户开始计算时,会创建一个实例,并启动一个任务。这个任务会监控status
字段(偶尔检查数据库)。当用户再次点击按钮时,视图会将状态改为user requested to stop
,这样任务就会终止。