- 浏览: 78016 次
- 性别:
- 来自: 上海
最新评论
-
rockythd:
视界这个概念终于搞清楚了,谢谢!
Java关于Scala的“视界(view bound)”的模拟 -
regular:
写了一个更通用的方法:ObjectUtils.cast。目的是 ...
Java关于Scala的“视界(view bound)”的模拟 -
lrztiancai:
谢谢分享。正在找这个!
Parsley+SpiceLib 2.4 Developer Manual -
kraft:
第二版什么时候出啊
Programming In Scala 翻译 -
justjavac:
xpf7622 写道haixu.huang@live @前的名 ...
Programming In Scala 翻译
原文地址:Java2D: Hardware Accelerating - Part2 - Buffer Strategies
利用我们已经学到的东西
昨天的帖子(Java2D: Hardware Acceletating - Part1 - Volatile Images)里,我讨论了java.awt.image.VolatileImage,以及如何使用它们(实现)双缓冲Java 2D的代码。如果你还不能实现,请先看一下那个帖子。今天的小提示将扩展引用那个提示里提供的例子。为了演示如何使用VolatileImage对象,我使用了一种极普通的代码格式来处理Java 2D代码 - 在例如java.awt.Canvas这样的对象中重载 paint(Graphics)方法,并在控件内部使用Graphics对象执行自定义画图。记住,正如前面的帖子中提到的以及对它的回复所述那样,如果你在做标准的AWT/Swing开发的话,这种重载并非很有用。在这种情况下,你通常应该依赖于已有的控件实现来优化渲染。我今天(以及昨天)所说的,只对你开发低层图像渲染,并且需要自己实现缓冲策略的工作很有用。通常这种情况发生在当你在使用Java开发2D游戏的时候。从这点出发我会与编写游戏结合讨论这一概念 - 我认为这是我可以提供的最实在的例子之一。
任何曾经实际写过游戏(使用几乎任何编程语言)的人可能都熟悉“游戏循环:game loop”这个概念。游戏循环实质就是这样的一系列步骤(我对此随便的命名,请原谅):
这个对游戏循环步骤地描述是很高层次的 - 但毕竟这样的过程易于理解 - 计算,渲染,等待。很不幸,我们的非恒定图像例子由于自身的设计不能支持。我们的渲染逻辑严格地捆绑在控件上,而不是我们的游戏循环。以下是用第一部分里面CustomGUI对象来实现的我们的游戏循环:
总结上面所发生的事情就是 - 我们实质上有两个重要线程 - AWT事件分发线程(处理绘制),以及游戏线程(处理游戏逻辑)。两个线程通过“repaint()”调用汇合。游戏逻辑在一个线程里,渲染代码在另外一个里。一旦游戏逻辑执行完毕,在AWT这边就请求一次repaint,实质是渲染我们游戏的另一“帧”。目前为止,这个逻辑也不是太复杂(除了昨天我们看到的CustomeGUI对象中恶心的VolatileImage逻辑)。然而,当我们开始尝试游戏逻辑与渲染之间的双向交流时,所有的东西就都错综复杂变得稀奇古怪了。为了让我们的基础变得更扎实,请允许我扩展昨天的例子。这里我打算把自定义的渲染分离成一个方法,这样就更容易分辨渲染的代码及更新的内容:
这个例子和昨天的代码唯一的差别就是我把实际绘制的代码拽出来成了doPaint(Graphics)方法。
接下来,让我们把线动起来。你问哪条线?哦,在doPaint方法的第四行我们画了一条10个像素的线。让我们把它动起来。(我知道,我真的知道,一条能动的线是枯燥乏味的 -你就假想它是在一点点啃食的蠕虫吧)。
让我们的线移动的第一步是把线的x坐标放在一个地方让我们的自定义画布渲染代码和更新代码都能访问到。很多方法都可以使用,不过目前最简单的就是作为MyGame类自身的静态变量:
这看上去就像是“入侵行为:hack”(的确是),但那也刚好演示了把渲染代码分离开来的第一个问题。必须实现复杂的结构,从而可以与渲染逻辑共享游戏算法的结果。我已经意识到了还有许多更优雅的方式解决这样的问题 - 不过我会稍后再描述一个更好的方法,因此请耐心等待。
接下来,我们要实现updateGameState()方法 - 记住,这个逻辑将在每一帧执行一次:
因此,长话短说,我们的小蠕虫将每一帧移动一个像素。现在我们只需更新doPaint方法基于此值渲染即可:
大功告成,我们现在实现了一个简单的小动画程序。我们没有处理用户输入或其它什么事,但至少我们已经让游戏循环全速工作了。
消除混淆
仍跟从我的人或许感觉我已经走到某条疯狂的歧路上并还在不断叫嚣着游戏开发呢吧。实际上,我还不至于失去职业操守(?原文:I haven't lost site of the prize)。我要使用我昨天讨论的东西实现所有这些逻辑,并使用今天小提示的原点 - 缓冲策略 - 把它们封装在一起。
当前使用于GUI代码的缓冲的模式(重载paint以实现VolatileImage对象)让人感觉不自然。我们在自定义的java.awt.Canvas对象内部实现绘图代码 - 然而按照道理说绘图逻辑应该是游戏代码的一部分,而不是Canvas对象自身的部分。那样的话,把这些逻辑移出来更好。另外,VolatileImage对象和缓冲策略感觉应该放在一起。当然某些比我们更聪明的人已经实现了这些缓冲算法,而且或许比我们做的还要好。
java.awt.image.BufferStrategy类可以填充我们当前实现的这两条缝隙 - 1.渲染逻辑可以与控件实现解耦,并且,2.缓冲策略可以与渲染逻辑解耦(并可以作为充分测试和优化的代码被重用)。
使用BufferStrategy类的一个最好的副作用是渲染代码可以在我们的游戏循环线程中序列执行(哦,好吧 - 伪序列地)。带来的好处是更好的状态变量可访问性(如lineX)因为我们不再需要跨越线程/类边界,而且也是的代码的交互更为清晰。
BufferStrategy对象可以由Frame和Canvas对象创建。一旦创建了,你就能对缓冲策略绘图(而不用考虑其实际的缓冲),然后把缓冲“冲”入主绘图对象。缓冲策略有各种全面的使用方法,不过在我们代码的例子里,我们只是简单的想把我们的复杂的缓冲逻辑用某些更干净更清晰的代码替代。我们想要的是能够被可用的硬件优化了的“双缓冲”(正如我们昨天提到的),并且我们可以使用现存的渲染逻辑做渲染。下面的是改编自java.awt.image.BufferStrategy的javadoc的简单例子:
比我们的CustomGUI怪兽要简单一点儿,哦?请注意我们一旦在缓冲策略中创建了Graphics对象,就可以像使用非恒定图像对象那样使用(渲染的算法没有改变)。同样请注意不像之前的那样,绘制代码不在事件分发线程中(尽管在这一幕的背后绘制仍然是在事件分发线程中完成的)。
那么这对我们的例子意味着什么呢?哦,简要的说这意味着我们可以几乎完全扔掉我们的CustomGUI画布子类了。我们唯一要保留的就是绘制代码本身!我家下来要奉献的就是使用缓冲策略对象把所有这些工作并为单一程序的集合体。主要目标之一就是去掉入侵的static变量 - 并且能够如此容易地做到这点部分要归功于使用BufferStrategy。那么,参见下面的代码 - 所有这些讨论的最终的结合体 - 使用了缓冲策略的我们的“动画”程序。
利用我们已经学到的东西
昨天的帖子(Java2D: Hardware Acceletating - Part1 - Volatile Images)里,我讨论了java.awt.image.VolatileImage,以及如何使用它们(实现)双缓冲Java 2D的代码。如果你还不能实现,请先看一下那个帖子。今天的小提示将扩展引用那个提示里提供的例子。为了演示如何使用VolatileImage对象,我使用了一种极普通的代码格式来处理Java 2D代码 - 在例如java.awt.Canvas这样的对象中重载 paint(Graphics)方法,并在控件内部使用Graphics对象执行自定义画图。记住,正如前面的帖子中提到的以及对它的回复所述那样,如果你在做标准的AWT/Swing开发的话,这种重载并非很有用。在这种情况下,你通常应该依赖于已有的控件实现来优化渲染。我今天(以及昨天)所说的,只对你开发低层图像渲染,并且需要自己实现缓冲策略的工作很有用。通常这种情况发生在当你在使用Java开发2D游戏的时候。从这点出发我会与编写游戏结合讨论这一概念 - 我认为这是我可以提供的最实在的例子之一。
任何曾经实际写过游戏(使用几乎任何编程语言)的人可能都熟悉“游戏循环:game loop”这个概念。游戏循环实质就是这样的一系列步骤(我对此随便的命名,请原谅):
- 过程阶段:基于用户输入和/或游戏事件更新任意“状态”变量
- 渲染阶段:基于“状态”变量执行UI渲染
- 同步阶段:睡眠直到某时刻以确保一致的帧速率
这个对游戏循环步骤地描述是很高层次的 - 但毕竟这样的过程易于理解 - 计算,渲染,等待。很不幸,我们的非恒定图像例子由于自身的设计不能支持。我们的渲染逻辑严格地捆绑在控件上,而不是我们的游戏循环。以下是用第一部分里面CustomGUI对象来实现的我们的游戏循环:
public class MyGame { private static final int FRAME_DELAY = 20; // 20ms。对应于50FPS (1000/20) = 50 private static Canvas gui; public static void main(String[] args) { JFrame frame = new JFrame(); gui = new CustomGUI(); // 创建我们自己的改造过渲染逻辑的Canvas对象 frame.getContentPane().add(gui); frame.setSize(500, 300); Thread gameThread = new Thread(new GameLoop()); gameThread.setPriority(Thread.MIN_PRIORITY); gameThread.start(); // 开始游戏过程 frame.setVisible(true); // 开始AWT绘制 } private static void updateGameState() { // 游戏逻辑 } private static class GameLoop implements Runnable { boolean isRunning = true; public void run() { int cycleTime = System.currentTimeMillis(); while(isRunning) { updateGameState(); MyGame.gui.repaint(); // 引发“paint”以在AWT线程中调用CustomGUI对象。(引发了帧的渲染) cycleTime = cycleTime + MyGame.FRAME_DELAY; long difference = cycleTime - System.currentTimeMillis(); try { Thread.sleep(Math.max(0, difference)); } catch(InterruptedException e) { e.printStackTrace(); } } } } }
总结上面所发生的事情就是 - 我们实质上有两个重要线程 - AWT事件分发线程(处理绘制),以及游戏线程(处理游戏逻辑)。两个线程通过“repaint()”调用汇合。游戏逻辑在一个线程里,渲染代码在另外一个里。一旦游戏逻辑执行完毕,在AWT这边就请求一次repaint,实质是渲染我们游戏的另一“帧”。目前为止,这个逻辑也不是太复杂(除了昨天我们看到的CustomeGUI对象中恶心的VolatileImage逻辑)。然而,当我们开始尝试游戏逻辑与渲染之间的双向交流时,所有的东西就都错综复杂变得稀奇古怪了。为了让我们的基础变得更扎实,请允许我扩展昨天的例子。这里我打算把自定义的渲染分离成一个方法,这样就更容易分辨渲染的代码及更新的内容:
// 也可扩展其它类 - 不过通常会选择Canvas public class CustomGUI extends Canvas { private VolatileImage volatileImg; // ... public void paint(Graphics g) { // 创建硬件加速图像 createBackBuffer(); // 主渲染循环。VolatileImage对象可能失去内容。 // 这个循环会不断渲染(如果需要的话并制造)VolatileImage对象 // 直到渲染过程圆满完成。 do { // 为该控件的Graphics配置验证VolatileImage的有效性。 // 如果VolatileImage对象不能匹配GraphicsConfiguration // (换句话说,硬件加速不能应用在新设备上) // 那我们就重建它。 GraphicsConfiguration gc = this.getGraphicsConfiguration(); int valCode = volatileImg.validate(gc); // 以下说明设备不匹配这个硬件加速Image对象。 if(valCode==VolatileImage.IMAGE_INCOMPATIBLE){ createBackBuffer(); // 重建硬件加速Image对象。 } Graphics offscreenGraphics = volatileImg.getGraphics(); doPaint(offscreenGraphics); // 调用核心paint方法。 // 把缓冲画回主Graphics对象 g.drawImage(volatileImg, 0, 0, this); // 检查内容是否丢失 } while(volatileImg.contentsLost()); } // 封装了渲染逻辑的新方法。 private void doPaint(Graphics g) { g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.BLACK); g.drawLine(0, 0, 10, 0); // 任意的渲染逻辑 } // 以下创建新的VolatileImage对象 private void createBackBuffer() { GraphicsConfiguration gc = getGraphicsConfiguration(); volatileImg = gc.createCompatibleVolatileImage(getWidth(), getHeight()); } public void update(Graphics g) { paint(g); } }
这个例子和昨天的代码唯一的差别就是我把实际绘制的代码拽出来成了doPaint(Graphics)方法。
接下来,让我们把线动起来。你问哪条线?哦,在doPaint方法的第四行我们画了一条10个像素的线。让我们把它动起来。(我知道,我真的知道,一条能动的线是枯燥乏味的 -你就假想它是在一点点啃食的蠕虫吧)。
让我们的线移动的第一步是把线的x坐标放在一个地方让我们的自定义画布渲染代码和更新代码都能访问到。很多方法都可以使用,不过目前最简单的就是作为MyGame类自身的静态变量:
public class MyGame { public static int lineX = 0; // ... }
这看上去就像是“入侵行为:hack”(的确是),但那也刚好演示了把渲染代码分离开来的第一个问题。必须实现复杂的结构,从而可以与渲染逻辑共享游戏算法的结果。我已经意识到了还有许多更优雅的方式解决这样的问题 - 不过我会稍后再描述一个更好的方法,因此请耐心等待。
接下来,我们要实现updateGameState()方法 - 记住,这个逻辑将在每一帧执行一次:
private void updateGameState() { lineX++; }
因此,长话短说,我们的小蠕虫将每一帧移动一个像素。现在我们只需更新doPaint方法基于此值渲染即可:
private void doPaint(Graphics g) { g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.BLACK); g.drawLine(MyGame.lineX, 0, MyGame.lineX + 10, 0); // 画图 }
大功告成,我们现在实现了一个简单的小动画程序。我们没有处理用户输入或其它什么事,但至少我们已经让游戏循环全速工作了。
消除混淆
仍跟从我的人或许感觉我已经走到某条疯狂的歧路上并还在不断叫嚣着游戏开发呢吧。实际上,我还不至于失去职业操守(?原文:I haven't lost site of the prize)。我要使用我昨天讨论的东西实现所有这些逻辑,并使用今天小提示的原点 - 缓冲策略 - 把它们封装在一起。
当前使用于GUI代码的缓冲的模式(重载paint以实现VolatileImage对象)让人感觉不自然。我们在自定义的java.awt.Canvas对象内部实现绘图代码 - 然而按照道理说绘图逻辑应该是游戏代码的一部分,而不是Canvas对象自身的部分。那样的话,把这些逻辑移出来更好。另外,VolatileImage对象和缓冲策略感觉应该放在一起。当然某些比我们更聪明的人已经实现了这些缓冲算法,而且或许比我们做的还要好。
java.awt.image.BufferStrategy类可以填充我们当前实现的这两条缝隙 - 1.渲染逻辑可以与控件实现解耦,并且,2.缓冲策略可以与渲染逻辑解耦(并可以作为充分测试和优化的代码被重用)。
使用BufferStrategy类的一个最好的副作用是渲染代码可以在我们的游戏循环线程中序列执行(哦,好吧 - 伪序列地)。带来的好处是更好的状态变量可访问性(如lineX)因为我们不再需要跨越线程/类边界,而且也是的代码的交互更为清晰。
BufferStrategy对象可以由Frame和Canvas对象创建。一旦创建了,你就能对缓冲策略绘图(而不用考虑其实际的缓冲),然后把缓冲“冲”入主绘图对象。缓冲策略有各种全面的使用方法,不过在我们代码的例子里,我们只是简单的想把我们的复杂的缓冲逻辑用某些更干净更清晰的代码替代。我们想要的是能够被可用的硬件优化了的“双缓冲”(正如我们昨天提到的),并且我们可以使用现存的渲染逻辑做渲染。下面的是改编自java.awt.image.BufferStrategy的javadoc的简单例子:
JFrame frame = new JFrame(); Canvas canvas = new Canvas(); frame.getContentPane().add(canvas); frame.setVisible(true); canvas.createBufferStrategy(2); // 创建2个缓冲(双缓冲)的缓冲策略 BufferStrategy strategy = canvas.getBufferStrategy(); Graphics g = strategy.getDrawGraphics(); // 绘制到Graphics对象 g.dispose(); // 把缓冲“冲”到主绘图区 strategy.show();
比我们的CustomGUI怪兽要简单一点儿,哦?请注意我们一旦在缓冲策略中创建了Graphics对象,就可以像使用非恒定图像对象那样使用(渲染的算法没有改变)。同样请注意不像之前的那样,绘制代码不在事件分发线程中(尽管在这一幕的背后绘制仍然是在事件分发线程中完成的)。
那么这对我们的例子意味着什么呢?哦,简要的说这意味着我们可以几乎完全扔掉我们的CustomGUI画布子类了。我们唯一要保留的就是绘制代码本身!我家下来要奉献的就是使用缓冲策略对象把所有这些工作并为单一程序的集合体。主要目标之一就是去掉入侵的static变量 - 并且能够如此容易地做到这点部分要归功于使用BufferStrategy。那么,参见下面的代码 - 所有这些讨论的最终的结合体 - 使用了缓冲策略的我们的“动画”程序。
public class MyGame { private static final int FRAME_DELAY = 20; // 20ms。对应于50FPS (1000/20) = 50 public static void main(String[] args) { JFrame frame = new JFrame(); Canvas gui = new Canvas(); frame.getContentPane().add(gui); frame.setSize(500, 300); frame.setVisible(true); // 开始AWT绘制 Thread gameThread = new Thread(new GameLoop(gui)); gameThread.setPriority(Thread.MIN_PRIORITY); gameThread.start(); // 开始游戏过程 } private static class GameLoop implements Runnable { boolean isRunning; int lineX; Canvas gui; long cycleTime; public GameLoop(Canvas canvas) { gui = canvas; isRunning = true; lineX = 0; } public void run() { cycleTime = System.currentTimeMillis(); gui.createBufferStrategy(2); BufferStrategy strategy = gui.getBufferStrategy(); // 游戏循环 while (isRunning) { updateGameState(); updateGUI(strategy); synchFramerate(); } } private void updateGameState() { lineX++; } private void updateGUI(BufferStrategy strategy) { Graphics g = strategy.getDrawGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, gui.getWidth(), gui.getHeight()); g.setColor(Color.BLACK); g.drawLine(lineX, 0, lineX + 10, 0); // 任意渲染逻辑 g.dispose(); strategy.show(); } private void synchFramerate() { cycleTime = cycleTime + FRAME_DELAY; long difference = cycleTime - System.currentTimeMillis(); try { Thread.sleep(Math.max(0, difference)); } catch(InterruptedException e) { e.printStackTrace(); } } } }
发表评论
-
把Spring容器中的bean绑定到通过代码创建的对象
2012-04-26 16:17 2277Spring提供了对配置中创建对象的字段实例注入。但如果是通过 ... -
动态注册消息类型及处理函数
2011-10-01 15:56 1007内容略。参见代码演示。 -
代码实例
2011-02-14 17:17 1032代码实例文件 -
如何在类外部调用被子类覆盖的父类方法
2011-01-20 14:46 1899题目比较绕。以下用一个简单的例子说明: public cl ... -
SWT应用的开发实例:没有使用到OSGi
2011-01-14 11:27 1530添加音效,以及中奖名单回看功能。 SWT应用一枚。具体方法见 ... -
运行期代码问题检查技术的研究
2010-11-29 13:30 1143以下用我之前代码中的一个bug作为说明,解释如何实现代码在运行 ... -
代码潜在故障的动态分析
2010-11-16 12:24 1520引子 大家都听说过FindBugs的大名。这是一款静态代码分析 ... -
健壮的、便捷的、异步的SocketChannel实现
2010-04-27 10:34 8396Socket通信比较常见的问题有如下几种: 1、设置收发超时; ... -
打算研究学习一下OSGi和Equinox
2010-02-10 11:26 1156看到一本很直接讨论这个题目的书,不过要等到3月1日才出来。 ... -
关键应用服务的集群技术模拟
2010-01-08 14:41 1082集群技术,也就是俗称的Cluster,是为了保证某种应用不间断 ... -
JarSpur 检查引用包归属的小工具
2009-12-25 17:31 1086图形化的界面,允许你导入任意多的在项目中可能需要的Jar包。 ... -
class.getResourceAsStream()与ClassLoader.getResourceAsStream()的区别
2009-11-11 17:33 2054在jar包里获得流形式的资源有两种方法,一个是Class.ge ... -
MultiKeyedMap方案的实现
2009-11-10 11:55 3760方案背景 所谓“MultiKey ... -
Java2D: 硬件加速 - 第一部分 - 非恒定图像类:Volatile Image
2009-10-30 16:19 4297原文地址:Java2D: Hareware Accelerat ... -
自建的MiniChart库,目前实现了点图、折线图、柱状图和饼图
2009-07-15 11:08 1245花了大约一个星期时间做的MiniChart库。 由于现在的免费 ... -
BM方案模式匹配的Java代码实现
2009-06-17 13:47 1585速度还算快,例子里比较的文件一共371个,3,293,472字 ... -
对于经典模式匹配算法的一些改动
2009-06-12 12:44 1490从一个很长的字符串(或者数组)中,查找某个子串(模式串)是否存 ... -
读写进程的互斥锁
2009-03-16 15:27 1591以下的代码完成了对某个资源的读写互斥锁,具体说明如下:1. 若 ... -
Object数组到泛型数组转换的伪解决方案
2009-01-23 10:44 4372闲来无事,想要用目前的Java技术模拟一个对象数据库。最初只是 ...
相关推荐
"Software Testing Strategies"这一章详细阐述了如何有效地进行软件测试。测试的主要目标是在交付给最终用户之前发现并修复错误。以下是对这一课件内容的深入解析: 首先,有效的测试策略始于技术审查。通过技术...
Fundamental data mining strategies, techniques, and evaluation methods are presented and implemented with the help of two well-known software tools. Several new topics have been added to the second ...
All levels of IT professionals, from executives responsible for determining IT strategies to systems administrators, to data analysts, to decision makers responsible for driving strategic initiatives,...
This guide is specifically designed for IT professionals and security experts who need to understand and implement robust strategies to protect their organization’s data. #### Key Knowledge Points:...
交易交易策略包含使用freqtrade的策略。 请注意,它们应该展示一些您可以在freqtrade上使用的指标和概念,并且可能不适用于投资目的。 因此,使用它们需要您自担风险。 这些功能中的许多功能也帮助我了解了api并发挥...
Chapter 2 Core Storm concepts Chapter 3 Topology design Chapter 4 Creating robust topologies Chapter 5 Moving from local to remote topologies Chapter 6 Tuning in Storm Chapter 7 Resource contention ...
5. **兼容性策略(Compatibility Strategies):** - 兼容性策略指导如何在不同版本的PostScript之间保持兼容性。 - 这些策略对于确保程序能够在不同的环境中运行非常重要。 通过以上内容,我们可以看出PostScript...
matlab中算法实现代码实现原理 什么是算法交易? 算法交易,也称为算法交易和黑盒交易,通常是指...场景一将购买(便宜的)第一家公司,然后卖空第二家(更昂贵的)公司的股票。 套利:如果满足以下三个条件之一,则可
- **BFS (Buffer File System):** An example of a disk-based filesystem. This section provides details on how BFS is implemented and managed. 8. **Execution Domains and Binary Formats (Section 3.8):**...
@ sirdiego / nuxt-auth-cognito-scheme 设置 使用npm安装: npm install --save @sirdiego/nuxt-auth-cognito-scheme 用纱安装: yarn add @sirdiego/nuxt... strategies : { cognito : { tokenType : "Bearer" ,
【标题】: "Translation-Strategies-of-Chinese-Neologism-into-English-商英.doc" 讨论的是汉语新词的英文翻译策略 【描述】: 这份文档是一个商务英语专业学生的毕业设计论文,研究如何将汉语新词准确地翻译成英文...
3. 零和决定策略(Zero-Determinant Strategies):是一种特定的博弈策略,其特点是无论对方采取何种策略,使用ZD策略的玩家总能保证自己获得相对固定的收益。 4. 社会福利(Social Welfare):在众包系统中,社会...
本书《Storm Applied: Strategies for real-time event processing》由Manning出版社出版,是关于Storm技术的实用指南,旨在帮助读者理解和掌握使用Storm进行实时事件处理的策略和技巧。 首先,书中对大数据的概念...
### Java Transaction Design Strategies知识点概述 #### 一、引言 《Java Transaction Design Strategies》是一本专注于Java事务设计的专业书籍,由Mark Richards编写。本书详细介绍了Java应用程序中的事务处理...
- **Overview of Box2D:** The book starts with an introduction to the core concepts and functionalities of Box2D, such as bodies, fixtures, shapes, and joints. - **Setting Up the Environment:** ...
- **例句**:“The company’s profits were boosted by innovative marketing strategies.”(公司的利润因为创新的营销策略而得到了提升。) - **派生词**: - booster (n.):支持者,推动器。 ### 18. ...
应用程序可测试基于人工智能的股票市场投资策略。 该计划有两种简单的投资策略来比较结果。 这些策略之一就是简单地购买和持有。 另一种是基于移动平均线的交叉以及使用相对强度指数或RSI的经典策略。 目前,该...
6. **数据库优化**:SQL查询优化、连接池管理、缓存策略(如使用Hibernate二级缓存)和事务管理,都是Java应用性能的关键因素。 7. **网络I/O优化**:使用NIO(Non-blocking I/O)可以提高处理大量并发连接的能力,...