Beyond Threading

Java线程模型与任务分解技术对比
本文探讨Java线程模型的优缺点,并对比基于任务(task-based)和消息传递(CSP)的现代并发技术,如Apple Grand Central Dispatch、Microsoft Task Parallel Library、Intel Thread Building Block等,以及它们在提高CPU效率、减少上下文切换开销等方面的应用。

Java线程模型的优点在于能够清晰的model应用逻辑流,通过对应OS里物理线程,可以利用多个处理器,或者通过切换让CPU利用率不同的线程共享一个处理器。

但是这种把应用的逻辑线程直接搬到OS的物理线程上运行的方式(*)也存在弊端:

  • Heavy weight,每个OS线程都需要内存和自己的堆栈等资源
  • Context switching,及其引起的低效率(cache污染,线程饥饿,优先级逆转..)
  • Synchronization & lock, 需用同步访问share memory和资源,而如何保证安全性,同时取得最大的效率, 如何平衡safety和liveness的关系解决起来绝非易事.

引起这些低效率很大原因是现有线程模式是粗线条的黑箱模式,runtime系统并不知道线程在干什么和它们之间的依赖关系,只是通过强制的方式(time slicing, locks, monitors)来调度协作。

另一种更加透明的方式,即把现有的线程分解成更小,轻量级的单位Task, 显示的描述这些任务单位之间的并行性和相互依赖关系,包括对同一资源的访问,有了这些信息,系统可以更高效的方式来执行这些任务。

具体的实现包括:

  • Apple Grand Central Dispatch
  • Microsoft Task Parallel Library
  • Intel Thread Building Block
  • Google Go Language

这些技术的模型都基于CSP(communicating sequential processing)

CSP模型里每个Process 内部是串行的,而Process和Process之间是并行的。这样overhead最小,更不需要有同步/锁的概念.系统的scheduler把高层模型映射到Runtime运行系统。

Runtime运行系统维护和cpu核数对等的线程池.每一个线程有自己的任务队列- double ended queue。线程从队列的头取得任务并执行,当本地队列为空时,则会从其他队列”偷”任务过来。通常情况下因为只有一个线程会访问队列的头所以不会有竞争,而队列尾出现竞争的情况也是空闲线程完成,实现了动态的自动的负载均衡和最高的CPU运行效率.

如果说GCD等基于task模型还比较低层的话,以Erlang为代表的Actor模型提供了更接近OO的抽象,同样是基于CSP,只不过Actor模型传的是message而不是closure。

Java库/框架推荐:

  • 开源的HawtDispatch库,Apple GCD 的Java实现, 作者也是ActiveMQ的开发人员,这个库短小精悍,可谓是最容易帮助上手Task based programming的工具了.http://hawtdispatch.fusesource.org/
  • 开源的Akka平台,构建于HawtDispatch之上,  功能强大:actor model, STM, 分布式+容错功能(接近Erlang). http://akkasource.org/

(*) Java5引入的Executor框架/ThreadPool只是改进但是没有解决根本的问题,另外Thread pool的queue本身是可能的瓶颈

转:http://www.tbdata.org/archives/1359

你遇到的错误: ``` ImportError: attempted relative import beyond top-level package ``` 是一个非常典型的 Python **相对导入越界错误**。它的根本原因是: > 你试图使用 `from ..db_config import DB_CONFIG` 这种“向上一级”的相对导入,但当前模块所在的包结构不完整或运行方式不支持相对导入。 --- ## 🔍 错误分析 你的目录结构大概是这样的: ``` D:\GaPinyc\SQLite_sync_Mysql\center_api\ ├── app.py ├── config/ │ └── db_config.py ├── models/ │ └── database.py ├── services/ │ └── data_sync.py ├── routes/ │ └── sync.py ``` 而你在 `models/database.py` 中写了: ```python from ..db_config import DB_CONFIG ``` 这意味着:从 `models/database.py` 向上退两层,找到 `db_config.py`。 但实际上: - `..` 是指 `models` 的父级(即 `center_api`) - 再 `..` 就是 `SQLite_sync_Mysql`,这里没有 `db_config.py` - 真正的 `db_config.py` 在 `config/` 目录下,并不在项目根目录! 所以这个相对路径是错的,而且 Python 把 `center_api` 当作顶级包(top-level package),不允许你用 `..` 跳出去。 --- ## ✅ 正确解决方案 ### ✅ 方案一:将 `config/db_config.py` 改为绝对导入(推荐) #### 步骤 1:确保项目根路径在 `sys.path` 中 修改 `app.py` 开头,手动加入项目根路径: ```python # app.py import sys import os # 获取当前文件所在目录(D:\GaPinyc\SQLite_sync_Mysql\center_api) current_dir = os.path.dirname(os.path.abspath(__file__)) # 将父目录(D:\GaPinyc\SQLite_sync_Mysql)加入 sys.path parent_dir = os.path.dirname(current_dir) if parent_dir not in sys.path: sys.path.insert(0, parent_dir) # 现在可以导入 config.db_config from routes.sync import sync_bp ``` #### 步骤 2:修改 `models/database.py` 使用绝对导入 ```python # models/database.py from config.db_config import DB_CONFIG # ✅ 绝对导入 import pymysql from pymysql.cursors import DictCursor import logging import threading local_data = threading.local() class Database: def __init__(self): pass def get_connection(self): if hasattr(local_data, "conn") and local_data.conn.open: try: local_data.conn.ping(reconnect=True) return local_data.conn except Exception: self.close() try: conn = pymysql.connect( host=DB_CONFIG["host"], user=DB_CONFIG["user"], password=DB_CONFIG["password"], database=DB_CONFIG["database"], port=DB_CONFIG["port"], charset=DB_CONFIG["charset"], autocommit=DB_CONFIG.get("autocommit", True), cursorclass=DictCursor ) local_data.conn = conn logging.info(f"🔗 成功连接到数据库: {DB_CONFIG['database']}@{DB_CONFIG['host']}") return conn except Exception as e: logging.error(f"❌ 数据库连接失败: {e}", exc_info=True) raise ConnectionError(f"无法连接到 MySQL: {e}") def close(self): if hasattr(local_data, "conn"): try: local_data.conn.close() logging.info("🔗 数据库连接已关闭") except Exception as e: logging.warning(f"⚠️ 关闭连接时出错: {e}") finally: delattr(local_data, "conn") ``` --- ### ✅ 方案二:把 `db_config.py` 移到 `center_api` 根目录下(简单粗暴) 如果你不想处理路径问题,可以直接: ``` copy config\db_config.py center_api\db_config.py ``` 然后在 `models/database.py` 中改为: ```python from db_config import DB_CONFIG # 直接同级导入 ``` 这样就不需要相对导入了。 > ⚠️ 缺点:配置文件分散,不利于多环境管理。 --- ### ✅ 方案三:使用环境变量 + 动态配置(生产推荐) 创建一个配置加载器: ```python # utils/config_loader.py import os import json def load_db_config(): # 优先从环境变量读取 return { "host": os.getenv("DB_HOST", "192.168.110.92"), "user": os.getenv("DB_USER", "admin"), "password": os.getenv("DB_PASSWORD", "gapinyc"), "database": os.getenv("DB_NAME", "board_db"), "port": int(os.getenv("DB_PORT", 3306)), "charset": "utf8mb4", "autocommit": False } ``` 然后在 `models/database.py` 中: ```python from utils.config_loader import load_db_config DB_CONFIG = load_db_config() ``` 完全避开导入问题。 --- ## 🛠 如何验证导入是否成功? 你可以临时加一行调试语句测试: ```python # 在 models/database.py 头部添加 import sys print("🔍 sys.path:", sys.path) ``` 看看 `D:\GaPinyc\SQLite_sync_Mysql` 是否在里面。 --- ## ✅ 最终建议结构与运行方式 ``` D:\GaPinyc\SQLite_sync_Mysql\ ├── center_api/ │ ├── app.py │ ├── routes/ │ ├── services/ │ ├── models/ │ └── config/ ← 注意!这个 config 应该和 center_api 同级? │ └── db_config.py ``` 更合理的做法是: ``` D:\GaPinyc\SQLite_sync_Mysql\ ├── config/ │ └── db_config.py ├── center_api/ │ ├── app.py │ ├── routes/ │ ├── services/ │ └── models/ └── app.py (启动入口) ``` 然后你在项目根目录运行: ```bash cd D:\GaPinyc\SQLite_sync_Mysql python center_api/app.py ``` 并在 `app.py` 中确保 `sys.path` 包含 `.` 和 `config/` 所在目录。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值