首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐
2025年5月19日 星期一 3:46pm

Java 帝国对 Python 的渗透能成功吗?

  • 24-03-05 03:21
  • 3555
  • 13069
blog.csdn.net

640?wx_fmt=gif

640?wx_fmt=jpeg

作者丨刘欣

责编 | 伍杏玲

本文经授权转载自码农翻身( ID:coderising)

 

2019年人工智能系统学:

https://edu.csdn.net/topic/ai30?utm_source=cxrs_bw

 

640?wx_fmt=png

引子

 

Java 帝国已经成立20多年,经过历代国王的励精图治,可以说是地大物博,码农众多。 

可是国王依然不满足,整天想着如何继续开拓疆土, 这一天晚上他又把几个重臣招来商议了。 

IO大臣说:“陛下,现在天下大势初定,我Java帝国已经占据了后端开发,大数据,Android开发等重要地盘,再想拓展殊为不易!” 

 “是啊, 前端被JavaScript所盘踞,我们很难渗透啊。” 线程大臣补充。 

国王点点头,这话不错,JavaScript一统前端,Flash消失了,Applet不见了。想到Applet,国王就一阵心痛,当时Java是靠了Applet才引起码农的关注,一炮走红,后来怎么就不行了呢?

“那人工智能呢?” 国王狠狠地问道。 

“陛下明鉴,人工智能底层都是C/C++的地盘,应用层被Python等所侵占。 ”  JDBC大臣回答。 

“云计算呢?” 

“似乎是Go语言的地盘。” 

 “嘶——” 国王觉得有点牙疼。 

IO大臣赶紧为君主分忧:“陛下,现在群雄涿鹿,八分天下,边境战火连年不息,陛下不仅维持住祖宗的基业,还有不小的扩展,已经是一代圣主了,不过多年征战,民力维艰,老臣有一计,也许能换来奇效。” 

 “爱卿快讲!” 

“老臣以为不战而屈人之兵才是上策,作为世界最强之王国,不仅要武力上震慑群雄,更要输出我堂堂Java帝国之文化和价值观。” 

 “什么文化和价值观?” 

“首先我们要大肆宣扬静态语言的种种好处,比如编译期检查发现错误,代码适合阅读和维护,适合大规模团队合作,口号我都想好了,就叫‘动态一时爽,重构火葬场!’ ” 

“嗯,这口号不错!” 国王赞许,“爱卿真是老成谋国。”

“可是有些语言也是静态的啊!你怎么宣传?” 老对头线程大臣发难。 

“陛下您想想,我们有很多宝贝,” IO大臣根本不理线程大臣, 继续侃侃而谈:“ 比如IoC、AOP、反射、动态代理、泛型、注解、JDBC、JMS......还有我们引以为豪的JVM。这些东西,那些国家可不一定有,我们派出老师,把这些东西灌输给他们的臣民,让他们体会到Java的种种好处,慢慢地就把他们给同化了!到时候他们的码农自然而然就会加入我Java帝国。”

“陛下万万不可,不同的语言有不同的特点,我们的文化别人是接受不了的,到时候只会引起群雄耻笑。” 线程大臣觉得IO大臣脑洞大开,简直是胡闹,非要误国不可。 

“可以一试嘛!” 国王牙不疼了,“此事由IO大臣全权负责,一年后看效果。”

 

640?wx_fmt=png

泛型

 

作为被派往Python王国的老师,吉森带着IO大臣的重托,风尘仆仆,终于来到了Python 王国。 

IO大臣在挑选人选的时候,有个重要的原则:是Java的死忠粉丝,最好是对其他语言根本不了解,省得思想被污染。 这吉森就是其中的佼佼者。

吉森先找到一个地方安顿下来,然后边四处闲逛, 他惊奇地发现,这里类方法中的self满天飞, 还有强制代码缩进,果然和我大Java不同,颇有异域风情。  

前面是个茶馆,人声鼎沸, 吉森走了进去,看看能不能牛刀小试,宣扬一下Java的文化。 

 “小二,我观察了半天,你们这里怎么没有讨论泛型啊?” 吉森拉住上茶的店小二。 

 “泛型? 那是什么东西? ” 小二大惑不解。  

“你肯定是个外乡人,不是来自C++就是Java,我说得没错吧?” 旁边不知道什么时候来了一个老头儿。 

“老先生眼光不错,我确实从Java王国来,我很纳闷,这里怎么没有泛型啊,据我所知,泛型可以在编译期做类型检查,码农们在写代码的时候也不需要做类型的转换,非常好用的啊。”  吉森开始灌输Java的种种好处。 

 

List<String> files = new ArrayList<String>(); 

String file = files.get(0);  //不必做强制类型转换 

files.add(new File(.....)) ;  // 编译错误  

“外乡人,我们Python中的变量是不需要声明类型的,不会做编译期类型检查,只有在运行时才会检查这个变量到底是什么类型,能否调用它的方法,你说,我们要泛型有什么用?” 

吉森大惊,卧槽,这IO大臣怎么没告诉自己啊, 人家根本就没这个需求! 

想想我大Java费了那么大劲儿去实现泛型,没想到在Python这里完全无用武之地, 还输出什么文化! 传什么教!

 

640?wx_fmt=png

反射

 

吉森觉得有点被IO大臣坑了! 不过多年的历练只是让他稍微慌乱,他马上稳住神,转移话题: “先生所言极是,晚生还有一个问题,这Python能支持反射吗? ” 

在Java王国,人们经常通过反射的方式来获取一个类的属性、方法,然后根据一个字符串的名称来调用某个类的方法。 

比如有个url :   /user?action=Login 

系统根据约定解析它,确定类是User, 方法是Login。然后就可以把User对象创建起来,通过反射调用Login 方法。 

 

public class User{
    public void login(...){
    ......
    }
}

“哈哈哈,你这个外乡人啊,你知道为什么我们Python是动态语言吗? 我们Python的反射功能不知道比你们Java强到哪里去了!来来来,我给你看个例子。” 

 

class User:
    def login(self):
        print("this is login")

“现在我打印他所有的方法:”  

 
 

methods = [x for x, y in User.__dict__.items() if type(y) == FunctionType]

print(methods)  #输出 ['login']

“接下来我通过反射调用Login方法, 老夫很久没写代码了,可能不太严谨,你明白意思就行。”

 

url = "/user?action=login"
#从url解析得到类和action,代码略
clz = "User"  
action = "login"
#根据名称获得User对象和方法
user = globals()[clz]()
func = getattr(user,action) #获取login方法
func() #输出This is login

吉森看到这么寥寥几行代码,就实现了基本的反射, 真是灵活啊,这Python真是不错,他都有点羡慕了。

 

640?wx_fmt=png

动态代理

 

不, 我肩负IO大臣的重托, 我是来传教的,不能让这老头儿给洗脑了! 

吉森想起来了一个大杀器:动态代理,这可是Java的一个非常基础的技术,可以在运行时实现类和方法的增强,比如在调用业务方法的前后加上事务管理,日志管理等功能,没有动态代理,AOP就别想了。

640?wx_fmt=png

吉森说道:“老先生,Python怎么去实现动态代理啊?”

老头儿微微一笑:“Java Class有个缺点, 一旦被装入Java虚拟机,就没法修改了,想对他做增强,只能修改字节码创建新的类,对老的类做封装,就是代理。但是Python是个动态语言,在运行时就可以修改啊,比如我可以动态地给User类增加一个新的属性,这一点你的Java做不到吧?”

 

setattr(User,"name",'andy')
print(user.name) #andy

吉森看得目瞪口呆,这真是颠覆了自己从小养成的世界观:一个类在运行期是不能改变的,更不可能去增加什么属性。

老头儿又接着说:“你看看这个User类,和Proxy类,每次调用Login方法的时候,我都可以动态地创建一个新的方法出来,在这个新的方法中,就可以做各种手脚了。”

 

class User:
    def login(self):
        print('user login')
    def logout(self):
        print('user logout')

class Proxy:

    def __init__(self, target):
        self.target = target

    def __getattribute__(self, name):
        target = object.__getattribute__(self, "target")
        attr = object.__getattribute__(target, name)

        if name == 'login'  :
            def newFunc(*args, **kwargs):  
                print ("login start")
                result = attr(*args, **kwargs)
                print( "login end")
                return result
            return newFunc
        else :
            return attr


u = User()
p = Proxy(u)

p.login() #实际上调用的是动态创建的方法
p.logout() #调用的是原来的方法

“你那个Proxy中的__getattribute__是什么东西啊? ” 吉森看到魔法都在这里,不由得发问。

“每当你去调用一个方法(如login/logout),或者访问一个字段的时候,Python都会通过__getattribute__先找到这个方法或者字段,然后才是真正的调用。”

“奥,原来如此,你通过__getattribute__做了手脚,如果名称是Login,就创建新的方法,在新的方法中除了调用老方法之外,还输出了日志。”

“不错,孺子可教!”

吉森现在是真心佩服动态语言了,在Java中必须得在运行时通过操纵字节码来增强,字节码啊,那可不是一般人能玩的。这Python居然在源码级别就把功能给增强了!

 

640?wx_fmt=png

锦囊妙计

 

吉森有点怀疑自己此次Python王国之行的效果了,这可如何是好? 怎么回去向IO大臣复命? 当初可是立下军令状的!

他突然想起临行前,IO大臣曾经送给自己三个锦囊,嘱咐自己只有到了最危急的时刻才能打开,现在不开,更待何时?

往怀中一摸,就发现锦囊只剩下了两个,丢了一个,这回去估计要杀头, 管不了那么多了, 吉森迅速掏出一个,只见上面写着一段话:GIL(全局解释锁),GIL是Python的命门,这把超级大锁只允许一个线程获得Python解释器的控制权, 简单来说,同一时刻,只有一个线程能运行!

没想到老头儿淡淡一笑:“Python确实有GIL,可是这程序的瓶颈啊,它不在CPU, 而在于IO,就是用户的输入,数据库的查许,网络的访问,线程等到有IO操作的时候,放弃GIL这个超级大锁,让别的线程去执行就是了。再说了,你真想利用多核的时候可以用多个进程啊!”

第一个锦囊妙计被轻松化解, 吉森赶紧掏出第二个,上面几个字:“动态一时爽,重构火葬场。”

“哈哈哈,”老头儿狡黠地笑了起来:“这都是不了解情况的外人的误解,听说过Quora没有?奥,上不了是吧!这Quora就是Python写的,人家那测试用例写得非常充分,重构也不怕! 所以啊关键是测试用例!”

第二个妙计又被化解, 吉森彻底没辙了。

 

640?wx_fmt=png

真相大白

 

看到吉森的神色变化,老头儿开始表明身份:“实不相瞒,老夫乃是Python国王的特使,我们的探子早就听说你们Java那什么破老师计划了,你一进入我国,就被盯上了,国王特地派我来,看看能不能说服你,留在我国。”

吉森想想,回去也无法交差,这Python似乎还不错,进退两难之际,不妨先妥协,以图将来,于是点点头答应了。

一年以后, IO大臣开始盘点老师计划,发现回来复命的寥寥无几,尤其是去Python王国的吉森, 他怎么一点消息都没有呢? 是时候再派一个人去了......

 

60s测试:你是否适合转型人工智能?

https://edu.csdn.net/topic/ai30?utm_source=cxrs_bw

640?wx_fmt=png

640?wx_fmt=jpeg

640?wx_fmt=gif

 热 文 推 荐 

☞程序员如何实现财富自由?

☞程序员下班后都忙些啥?| 程序员有话说

☞为什么程序员下班后只关显示器从不关电脑?

☞华为小米入场,能拯救乐视互联网电视挖的坑吗?

☞暴雪游戏遭遇AI“实力”坑队友:四处游走,还不参与战斗

☞《流浪地球》票房:预测10亿却飚50亿 ,数据预测为什么这么难

☞如果中本聪没说错,这场战争美国输定了!

☞神操作!这段代码让程序员躺赚200万?给力!

 

print_r('点个好看吧!');
var_dump('点个好看吧!');
NSLog(@"点个好看吧!");
System.out.println("点个好看吧!");
console.log("点个好看吧!");
print("点个好看吧!");
printf("点个好看吧!\n");
cout << "点个好看吧!" << endl;
Console.WriteLine("点个好看吧!");
fmt.Println("点个好看吧!");
Response.Write("点个好看吧!");
alert("点个好看吧!")
echo "点个好看吧!"

640?wx_fmt=png喜欢就点击“好看”吧

程序人生
微信公众号
笑谈开发轶事,品味程序人生。

1. 业务场景与挑战

每日订单量1000万级,数据规模呈指数级增长:

  • 年度数据量达36亿条
  • 单表容量突破2000万性能临界点
  • 高峰期并发请求量超过5万QPS

核心挑战聚焦三大维度:

  1. 存储成本:海量数据物理存储成本激增
  2. 查询效率:多维度组合查询响应超时
  3. 并发压力:实时订单状态查询流量洪峰

2. 存储压力如何解决

  1. 如何保证大数据量存储

通过分库分表

如何拆分?买家和卖家是否需要分开存储?

分开存储扩展已经查询性能都会好一些。

  1. 如何分库?

分库策略,通过用户ID 或者订单创建时间 取模 分库数量

分表策略:每个库内按月份分表

  1. 数据都要存储到数据库吗?

对于很多数据在近期都不会被查询,所以可以将数据做一个拆分,冷数据 and 热数据。

30 天内的数据 -> MySQL

超过30天的数据 -> TiDB or ClickHouse ...

3. 复杂业务场景如何解决?

举个例子,比如查询卖家过去30天内金额>100元且为己完成状态的某类订单?

通过ES是不是更加高效?

  • 索引设计:建立seller_id + create_time + order_status联合索引
  • 数据同步:基于Binlog实现准实时同步
json
代码解读
复制代码
// 多条件组合查询DSL优化 {  "query": {    "bool": {      "filter": [       {"term": {"seller_id": 98765}},       {"range": {"create_time": {"gte": "now-30d/d"}}},       {"script": {"script": "doc['order_amount'].value >= 100"}}     ],      "must": [       {"term": {"order_status": "completed"}},       {"match": {"order_type": "takeout"}}     ]   } },  "preference": "primary_first" // 优先主分片提升稳定性 } ​

4. 热点数据查询如何解决?

对于热点数据,查询 ES 或者 MySQL 无疑是带来很大压力以及性能也会比较差。

举个例子,买家查询最近10条订单数?卖家最近1天内所有订单列表;

对于这种热点数据,我们可以缓存到 Redis 中,对于热点数据存储到Redis就好,查询中走Redis查询性能也会提升大一些。

  1. 比如买家查询最近10条订单(读多写少场景)
ruby
代码解读
复制代码
# Key: 用户维度 + 业务标识 buyer:orders:{user_id}:recent  # 例如 buyer:orders:12345:recent ​ # Value: 用 Redis List 存储订单ID(按时间倒序) [  "order_id_100",  # 最新订单  "order_id_99", ...  "order_id_91"    # 第10条订单 ] ​ # 或用 Hash 存储订单详情(如果需缓存完整数据) {  "order_id_100": "{订单JSON}",  "order_id_99": "{订单JSON}", ... } ​
  1. 卖家最近1天内订单列表(高频过滤查询)
csharp
代码解读
复制代码
# Key: 卖家ID + 时间范围 seller:orders:{seller_id}:last_24h  # 例如 seller:orders:98765:last_24h ​ # Value: 用 Sorted Set (ZSET) 存储订单ID和创建时间戳 # Score = 订单时间戳, Member = 订单ID [ [1640995200, "order_id_100"], [1640995201, "order_id_101"], ... ] ​ # 或用 Hash 存储订单详情(按需) {  "order_id_100": "{订单JSON}",  "order_id_101": "{订单JSON}", ... } ​

5. 总结

对于存储压力比较大,可以采用分库分表优化,采用合理的分库分表手段以及分片键的选取。对于久远数据,为了避免干扰目前的查询,可以采用冷热数据分离。

为了解决复杂的查询条件,可以采用ES查询优化。

对于热点数据,可以采用将近期内的订单数据缓存到 Redis 中,利用 Redis 性能高的特性,以及引入本地缓存构建多级缓存体系进行优化。

注:本文转载自blog.csdn.net的CSDN 程序人生的文章"https://blog.csdn.net/csdnsevenn/article/details/88047921"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top