x-blog之在线编程简单介绍

前言

该模块是在认认真真理解并动手完成马士兵老师代理模式的情景下完成,目前实现方法和旧版本一样

简单分析

这里遇到一个问题,如何高效率执行并发在线编程?
这个最终的解决办法并不是很好,但是探索的过程总是充满乐趣

  1. 怎么才能实现在线编程?
    刚开始用记事本写java的时候,对这个问题肯定贼深刻,但随着工具的方便性,很多底层的东西越来越变得不透明。
    其具体思路就是代码变成字符串,然后拿到当前编译器进行编译,最后将编译的结果输出即可。
    但是如果不加以控制的话,最后如果并发量大的话,同时写入和读出造成错误,会使编译效率很低

2.如何保证编译并行执行?
由于个人经验和能力问题,这个问题最终没有本解决。但是探索的过程是很有趣的。
记得当时首先使用lock写锁,控制。假设是单线程执行,一个用户写完还必须按照时间等待,并发量高效率很低。很自然想到线程池,封装一个线程池工具类,创建一个编译线程任务类,然后就是按照线程创建时间创建不同的文件夹,每个文件夹来自不同的用户线程,这样就解决了记录问题,剩下就是怎么保证每个用户都知道自己执行哪个编译线程,然后拿到对应的编译结果(在这里遇到了瓶颈)
Alt text
最终是可以并行执行编译,而不是串行等待,但是编译的结果随机发给了等待的用户,当然可以直接用synchronized控制同步,但是代价和执行效果就不怎么好了。

3.低效的解决办法
最后直接用synchronized控制同步,也就没有必要使用线程池了,只要保证不同用户编译和返回的结果是正确就行了
旧版本将该功能做成微服务,利用dubbo管理,这样尽可能降低并发带来的性能问题

码上有戏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
@Override
public String getCompileResult(String originStr) {
// 1.创建需要动态编译的代码字符串
// 回车
String nr = "\r\n";
String source = "package temp.com; " + nr + originStr;
// 2.将欲动态编译的代码写入文件中 1.创建临时目录 2.写入临时文件目录
File dir = new File(System.getProperty("user.dir") + "/temp");
// 如果 \temp 不存在 就创建
if (!dir.exists()) {
dir.mkdir();
}
logger.info(dir.toString());
FileWriter writer;
try {
writer = new FileWriter(new File(dir, "Main.java"));
writer.write(source);
writer.flush();
writer.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 3.取得当前系统的编译器
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
// 4.获取一个文件管理器
StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager(null, null, null);
// 5.文件管理器根与文件连接起来
Iterable it = javaFileManager.getJavaFileObjects(new File(dir, "Main.java"));
// 6.创建编译任务
JavaCompiler.CompilationTask task =
javaCompiler.getTask(null, javaFileManager, null, Arrays.asList("-d", "./temp"), null, it);
boolean k = false;
Exception ee = new RuntimeException();
try {
// 7.执行编译
k = task.call();
if (!k) {
return "sorry ! your code has some problems,please check!";
}
// 8.运行程序
Runtime run = Runtime.getRuntime();
Process process = null;
try {
try {
process = run.exec("java -cp ./temp temp/com/Main");
}
catch (Exception e) {
e.printStackTrace();
}
InputStream in = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String info;
StringBuilder sb = new StringBuilder();
try {
while ((info = reader.readLine()) != null) {
sb.append(info + "<br/>");
}
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info(sb.toString());
return sb.toString();
}
catch (RuntimeException e) {
return "err";
}
}
finally {
}
}

热评文章