既然字符串方案行不通,我们回到最初的代码,看看有没有什么思路
public class AsyncUtils {
/**
* <br>定长线程池,目前大小为20
*/
private static final ExecutorService EXECUTOR_SERVICE = (ExecutorService) Executors.newFixedThreadPool(20);
public static void run(Runnable task){
EXECUTOR_SERVICE.execute(task);
}
在run
方法里,我们只拿到了一个 Runnable
对象
这个对象肯定包含了 类名
方法名
参数列表
等参数,不然怎么能被 run
的,对吧
那么我们如何去获得这些信息呢?
网上搜了一圈,无果
自己debug
调试,也没看出啥来
既然白盒方式行不通,那么黑盒行不行呢?
也就是:我直接把这个Runnable
对象整个存起来,用的时候还原回来用
序列化
是非常适合 整个存起来
整个概念的
序列化 第一关
我们来写下代码
public static void run(Runnable task){
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(task);
byte[] byteArray = byteArrayOutputStream.toByteArray();
}
思路就是把Runnable
对象,通过序列化的方式转为 byte 数组(byte 数组不论存为什么形式都方便)
实际执行代码的时候,抛出异常,提示 task 不是一个可序列化的对象
但是我们的 task
是 lambda
自动生成的,我们也控制不了呀,怎么办呢?
网上搜了下,找到了解决办法
这是博客
)
我们在调用的时候换下写法就行
//之前的写法
AsyncUtils.run( () -> genGroupUnit(groupId, agentId));
//之后的写法
AsyncUtils.run( (Runnable & Serializable)() -> genGroupUnit(groupId, agentId));
加上 (Runnable & Serializable)
,把这个对象强转一下,lambda
就自动对生成的内部匿名类进行序列化了
用代码测试
AsyncUtils.run( () -> System.out.println("Can I be serialized?"));
OK了,反序列化也正常打印
但是,等等,我们项目中用到异步任务的,难道都是打印吗?
序列化 第二关
我们来试试实际代码
AsyncUtils.run( (Runnable & Serializable)() -> genGroupUnit(groupId, agentId));
发现还是抛一样的错误
其实也好理解,genGroupUnit
是调用类的一个方法,序列化的时候,这个类也需要序列化
那我们让这个类 implements Serializable
并且自动生成一个 serialVersionUID
再次运行,咦,依然报错
序列化 第三关
网上搜了搜,看到一篇文章
总结出来的意思就是:
只要打算序列化一个类,那么这个类本身要实现序列化,
且如果其成员变量不是 transient
类型的,那么也需要实现序列化
那么问题来了,我们的是 spring
工程,成员变量各种 @Autowired
Service @Autowired
其他 Service, Service 还 @Autowired
DAO
工作量太大,不太现实
即使不考虑工作量的问题,最后所有的 Bean
都实现序列化了,
那么序列化出来的对象,是不是把整个 IOC
给打包了呢?(未尝试,不知道是不是这个场景)
如果是的话,那这个对象太大了,耗性能,耗IO
综上, 序列化方案
不适合我的需求
(只适合微型项目)
参考
http://www.importnew.com/24490.html
https://codeday.me/bug/20170623/25925.html
网友评论