- 浏览: 1011155 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (826)
- 硬件 (8)
- 软件 (24)
- 软件工程 (34)
- JAVA (229)
- C/C++/C# (77)
- JavaScript (8)
- PHP (1)
- Ruby (3)
- MySQL (14)
- 数据库 (19)
- 心情记事 (12)
- 团队管理 (19)
- Hadoop (1)
- spring (22)
- mybatis(ibatis) (7)
- tomcat (16)
- velocity (0)
- 系统架构 (6)
- JMX (8)
- proxool (1)
- 开发工具 (16)
- python (10)
- JVM (27)
- servlet (5)
- JMS (26)
- ant (2)
- 设计模式 (5)
- 智力题 (2)
- 面试题收集 (1)
- 孙子兵法 (16)
- 测试 (1)
- 数据结构 (7)
- 算法 (22)
- Android (11)
- 汽车驾驶 (1)
- lucene (1)
- memcache (12)
- 技术架构 (7)
- OTP-Erlang (7)
- memcached (17)
- redis (20)
- 浏览器插件 (3)
- sqlite (3)
- Heritrix (9)
- Java线程 (1)
- scala (0)
- Mina (6)
- 汇编 (2)
- Netty (15)
- libevent (0)
- CentOS (12)
- mongod (5)
- mac os (0)
最新评论
-
kingasdfg:
你这里面存在一个错误添加多个任务 应该是这样的 /** * ...
Quartz的任务的临时启动和暂停和恢复【转】 -
kyzeng:
纠正一个错误,long型对应的符号是J,不是L。
Jni中C++和Java的参数传递 -
zhaohaolin:
抱歉,兄弟,只是留下作记录,方便学习,如果觉得资料不好,可以到 ...
netty的个人使用心得【转】 -
cccoooccooco:
谢谢!自己一直以为虚机得使用网线才可以与主机连接呢。。
主机网卡无网线连接与虚拟机通信 -
yuqilin001:
要转别人的东西,请转清楚点嘛,少了这么多类,误人子弟
netty的个人使用心得【转】
Object中的同步机制
作者:qixiaorui 日期:2009-04-30 09:32:20
robot.JPG(20.0 K) |
程序不是玩具,必须具备商业运作的稳定性。所以在运行的时候要充分考虑不同线程之间的同步性。在使用同步性技术的时候,考虑到标志布尔型变量与while循环搭配的效果容易对CPU造成很大的资源浪费,所以在这里采取了wait+notify技术。
Java在设计之初就充分考虑到了线程同步的问题,因而在设计基础类Oject的时候就为其提供了基于同步技术的三个函数wait+notify+notifyAll。这就意味着你所编写的任何类都可以使用这些方法(虽然在某些时候这些方法是根本没有意义的)。
我们知道,Thread对象的sleep()方法也可以使当前线程暂停运行。但sleep()方法和wait()方法从本质上来说是不一样的。sleep()使得一个进程进入睡眠状态,但其线程所占有的资源并没有释放。假设,你在synchronized模块(加函数锁或者对象锁)里调用了sleep(),虽然线程睡着了而且没有使用资源,但是它依然保存着锁,别的线程依然无法调用相关的synchronized模块。而wait()则不同,它实际上了是放弃了锁,将资源贡献出来,而使自己暂时离岗。这个离岗状态一直会持续到“boss”(其他的线程)调用了notify(),通知线程继续回来工作为止。
关于线程同步的三个函数,JAVA DOC中是这样描述的:
wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行.
notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。此方法只应由作为此对象监视器的所有者的线程来调用.
"当前的线程必须拥有此对象监视器"与"此方法只应由作为此对象监视器的所有者的线程来调用"说明wait方法与notify方法必须在同步块内执行,即synchronized(obj之内).
调用对像wait方法后,当前线程释放对像锁,进入等待状态.直到其他线程(也只能是其他线程)通过notify 方法,或 notifyAll.该线程重新获得对像锁.
继续执行,记得线程必须重新获得对像锁才能继续执行.因为synchronized代码块内没有锁是寸步不能走的.
下面我举一个实际例子来说明线程的同步问题:
例子非常通俗易懂。我将构造一个机器人。该机器人有一个身子,两只胳膊和两条腿。除了身子不动外,头、腿和胳膊要有节律地运动。因为每个零件的运动都在单独的一个线程内,所以要想让胳膊和腿按照一定的顺序执行,必须使用同步机制。
首先来看一个无规律运动的实例代码:
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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
package ql.abs; import java.io.*; import java.text.*; import java.util.*; import java.net.*; import quanwen.*; //常用函数 import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import javax.swing.border.*; import java.util.Iterator; import java.util.List; /** * 一个未基于线程同步的小机器人 */ public class ExpNoSync extends JFrame{ JPanel pnlTop=new JPanel(), pnlBottom=new JPanel(); JPanel pnlTopLeft=new JPanel(), pnlTopRight=new JPanel(), pnlTopCenter=new JPanel(); JPanel armLeft=new Arm1(), pnlTopLeft2=new JPanel(); JPanel armRight=new Arm2(), pnlTopRight2=new JPanel(); JPanel pnlBottomLeft=new JPanel(), leg=new Leg(), pnlBottomRight=new JPanel(); JPanel head=new Head(); Container c; public ExpNoSync(){ super("小机器人"); armLeft.setPreferredSize(new Dimension(50,50)); pnlTopLeft2.setPreferredSize(new Dimension(50,50)); pnlTopCenter.setBackground(Color.white); pnlTopCenter.setPreferredSize(new Dimension(50,50)); armRight.setPreferredSize(new Dimension(50,50)); pnlTopRight2.setPreferredSize(new Dimension(50,50)); pnlBottomLeft.setPreferredSize(new Dimension(50,50)); leg.setPreferredSize(new Dimension(50,50)); pnlBottomRight.setPreferredSize(new Dimension(50,50)); c=getContentPane(); c.setLayout(new GridLayout(3,3,0,0)); c.add(pnlBottomLeft); c.add(head); c.add(pnlBottomRight); c.add(armLeft); c.add(pnlTopCenter); c.add(armRight); c.add(pnlTopRight2); c.add(leg); c.add(pnlTopRight); setSize(167,160); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); show(); } public static void main(String[] args){ ExpNoSync exp=new ExpNoSync(); } class Arm1 extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblArm1=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblArm1.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ //休眠1秒钟 while(true){ try{ this.sleep(500); }catch(Exception ex){return;} SwingUtilities.invokeLater(changeIt); step++; if(step>1) step=0; } } }; public Arm1(){ icon[0]=new ImageIcon(Arm1.class.getResource("image/armLeft1.GIF")); icon[1]=new ImageIcon(Arm1.class.getResource("image/armLeft2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblArm1.setIcon(icon[step]); add(lblArm1); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } class Arm2 extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblArm2=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblArm2.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ //休眠1秒钟 while(true){ try{ this.sleep(500); }catch(Exception ex){return;} SwingUtilities.invokeLater(changeIt); step++; if(step>1) step=0; } } }; public Arm2(){ icon[0]=new ImageIcon(Arm2.class.getResource("image/armRight1.GIF")); icon[1]=new ImageIcon(Arm2.class.getResource("image/armRight2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblArm2.setIcon(icon[step]); add(lblArm2); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } class Leg extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblLeg=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblLeg.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ //休眠1秒钟 while(true){ try{ this.sleep(500); }catch(Exception ex){return;} SwingUtilities.invokeLater(changeIt); step++; if(step>1) step=0; } } }; public Leg(){ icon[0]=new ImageIcon(Leg.class.getResource("image/leg1.GIF")); icon[1]=new ImageIcon(Leg.class.getResource("image/leg2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblLeg.setIcon(icon[step]); add(lblLeg); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } class Head extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblHead=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblHead.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ //休眠1秒钟 while(true){ try{ this.sleep(500); }catch(Exception ex){return;} SwingUtilities.invokeLater(changeIt); step++; if(step>1) step=0; } } }; public Head(){ icon[0]=new ImageIcon(Head.class.getResource("image/head1.GIF")); icon[1]=new ImageIcon(Head.class.getResource("image/head2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblHead.setIcon(icon[step]); add(lblHead); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } } |
瞬间捕捉的图形如下:
从运行效果上看,因为眼睛、手、脚都没有使用同步机制,所以其运动是没有规律的。现在我们为它加上同步机制,要求按照先动眼睛,再动左手,再动右手,最后动脚的顺序循环播放,更改后的代码如下:
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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
package ql.abs; import java.io.*; import java.text.*; import java.util.*; import java.net.*; import quanwen.*; //常用函数 import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import javax.swing.border.*; import java.util.Iterator; import java.util.List; /** * 一个基于线程同步的机器人 */ public class ExpSync extends JFrame{ Object headLock = new Object(); Object arm1Lock = new Object(); Object arm2Lock = new Object(); Object legLock = new Object(); JPanel pnlTop=new JPanel(), pnlBottom=new JPanel(); JPanel pnlTopLeft=new JPanel(), pnlTopRight=new JPanel(), pnlTopCenter=new JPanel(); JPanel armLeft=new Arm1(), pnlTopLeft2=new JPanel(); JPanel armRight=new Arm2(), pnlTopRight2=new JPanel(); JPanel pnlBottomLeft=new JPanel(), leg=new Leg(), pnlBottomRight=new JPanel(); JPanel head=new Head(); Container c; public ExpSync(){ super("小机器人"); armLeft.setPreferredSize(new Dimension(50,50)); pnlTopLeft2.setPreferredSize(new Dimension(50,50)); pnlTopCenter.setBackground(Color.white); pnlTopCenter.setPreferredSize(new Dimension(50,50)); armRight.setPreferredSize(new Dimension(50,50)); pnlTopRight2.setPreferredSize(new Dimension(50,50)); pnlBottomLeft.setPreferredSize(new Dimension(50,50)); leg.setPreferredSize(new Dimension(50,50)); pnlBottomRight.setPreferredSize(new Dimension(50,50)); c=getContentPane(); c.setLayout(new GridLayout(3,3,0,0)); c.add(pnlBottomLeft); c.add(head); c.add(pnlBottomRight); c.add(armLeft); c.add(pnlTopCenter); c.add(armRight); c.add(pnlTopRight2); c.add(leg); c.add(pnlTopRight); setSize(167,160); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); show(); //每隔4秒为arm1线程解锁一次 Arm1Released ar=new Arm1Released(); ar.start(); } public static void main(String[] args){ ExpSync exp=new ExpSync(); } //为线程锁链中的左边胳膊解锁 class Arm1Released extends Thread{ public void run(){ while(true){ try{ this.sleep(4000); }catch(Exception ex){} //为arm1解锁 synchronized(arm1Lock) { arm1Lock.notify(); } System.out.println("--- Send arm1Lock notify..."); } } } //左边的胳膊 class Arm1 extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblArm1=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblArm1.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ //休眠1秒钟 while(true){ System.out.println("arm1 is locked"); //arm1等待head来解锁 synchronized (arm1Lock) { try { arm1Lock.wait(); } catch (InterruptedException ie) { System.out.println(ie.toString()); } } System.out.println("arm1 is released"); SwingUtilities.invokeLater(changeIt); try{ Thread.currentThread().sleep(1000); }catch(Exception ex){} //arm1为arm2解锁 synchronized(arm2Lock) { arm2Lock.notify(); } System.out.println("--- Send arm2Lock notify..."); step++; if(step>1) step=0; } } }; public Arm1(){ icon[0]=new ImageIcon(Arm1.class.getResource("image/armLeft1.GIF")); icon[1]=new ImageIcon(Arm1.class.getResource("image/armLeft2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblArm1.setIcon(icon[step]); add(lblArm1); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } class Arm2 extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblArm2=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblArm2.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ //休眠1秒钟 while(true){ System.out.println("arm2 is locked"); //arm2等待arm1来解锁 synchronized (arm2Lock) { try { arm2Lock.wait(); } catch (InterruptedException ie) {} } System.out.println("arm2 is released"); SwingUtilities.invokeLater(changeIt); try{ Thread.currentThread().sleep(1000); }catch(Exception ex){} //arm2为leg解锁 synchronized(legLock) { legLock.notify(); } System.out.println("--- Send legLock notify..."); step++; if(step>1) step=0; } } }; public Arm2(){ icon[0]=new ImageIcon(Arm2.class.getResource("image/armRight1.GIF")); icon[1]=new ImageIcon(Arm2.class.getResource("image/armRight2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblArm2.setIcon(icon[step]); add(lblArm2); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } class Leg extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblLeg=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblLeg.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ //休眠1秒钟 while(true){ System.out.println("leg is locked"); //leg等待arm2来解锁 synchronized (legLock) { try { legLock.wait(); } catch (InterruptedException ie) {} } System.out.println("leg is released"); SwingUtilities.invokeLater(changeIt); try{ Thread.currentThread().sleep(1000); }catch(Exception ex){} //leg为head解锁 synchronized(headLock) { headLock.notify(); } System.out.println("--- Send headLock notify..."); step++; if(step>1) step=0; } } }; public Leg(){ icon[0]=new ImageIcon(Leg.class.getResource("image/leg1.GIF")); icon[1]=new ImageIcon(Leg.class.getResource("image/leg2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblLeg.setIcon(icon[step]); add(lblLeg); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } class Head extends JPanel{ ImageIcon[] icon=new ImageIcon[2]; int step=0; JLabel lblHead=new JLabel(); Runnable changeIt=new Runnable(){ public void run(){ lblHead.setIcon(icon[step]); } }; Thread t=new Thread(){ public void run(){ while(true){ System.out.println("head is locked"); //head等待leg来解锁 synchronized (headLock) { try { headLock.wait(); } catch (InterruptedException ie) {} } System.out.println("head is released"); SwingUtilities.invokeLater(changeIt); try{ Thread.currentThread().sleep(1000); }catch(Exception ex){} //head为arm1解锁 synchronized(arm1Lock) { arm1Lock.notify(); } System.out.println("--- Send arm1Lock notify..."); step++; if(step>1) step=0; } } }; public Head(){ icon[0]=new ImageIcon(Head.class.getResource("image/head1.GIF")); icon[1]=new ImageIcon(Head.class.getResource("image/head2.GIF")); setLayout(new FlowLayout(FlowLayout.RIGHT)); lblHead.setIcon(icon[step]); add(lblHead); t.start(); } public Dimension getPreferredSize(){ return new Dimension(50,50); } } } |
从代码可以看出。左胳膊Arm1先是阻塞自己,等待Arm1Released线程或Head线程释放自己,当自己被释放以后,则释放Arm2。右胳膊Arm2先是阻塞自己,等待Arm1线程释放自己,当自己被释放以后,则释放leg。腿Leg先是阻塞自己,等待Arm2线程释放自己,当自己被释放以后,则释放head。头Head先是阻塞自己,等待Leg线程释放自己,当自己被释放以后,则释放Arm1。
因为左胳膊,右胳膊,腿,头三个线程之间不存在先后执行的问题,所以你在实际运行中会看到以下的顺序:
arm1 is locked
arm2 is locked
leg is locked
head is locked
--- Send arm1Lock notify --- 1、 Arm1Released线程释放Arm1
arm1 is released 2、 arm1被Arm1Released释放
--- Send arm2Lock notify... 3、 arm1释放arm2
arm1 is locked
arm2 is released 4、 arm2被arm1释放
--- Send legLock notify... 5、 arm2释放leg
arm2 is locked
leg is released 6、 leg被arm2释放
--- Send headLock notify... 7、 leg释放head
leg is locked
head is released 8、head被leg释放
--- Send arm1Lock notify... 9、head释放arm1
head is locked
arm1 is released 10、arm1被head释放
--- Send arm1Lock notify --- 11、Arm1Released线程释放Arm1
--- Send arm2Lock notify... 12、arm1释放arm2
arm1 is locked
arm2 is released 13、……
--- Send legLock notify...
arm2 is locked
程序开始运行构造函数中几个机器人的部件都被初始化,四个部件均被自己阻塞,如果Arm1Released不运行,则四个线程都无法继续工作。即无法执行释放别人的操作而造成整个程序死锁。
发表评论
-
调试jdk中的源码,查看jdk局部变量
2013-06-15 23:30 1048调试jdk中的源码,查看jdk局部变量 2012-04 ... -
Eclipse快捷键 10个最有用的快捷键<转>
2013-04-11 23:28 1070Eclipse中10个最有用的快捷键组合 一个Eclip ... -
Lucene 3.6 中文分词、分页查询、高亮显示等
2012-12-09 23:35 18101、准备工作 下载lucene 3.6.1 : htt ... -
Maven实战(九)——打包的技巧(转)
2012-10-12 00:41 932“打包“这个词听起 ... -
基于Maven的web工程如何配置嵌入式Jetty Server开发调试环境(转)
2012-10-12 00:28 9161、首先在web工程的POM文件里添加依赖jar包如下: ... -
轻轻松松学Solr(1)--概述及安装[转]
2012-09-18 14:59 990概述 这段时间对企 ... -
分析Netty工作流程[转]
2012-09-04 19:02 883下面以Netty中Echo的例 ... -
让eclipse在ubuntu下面好看一点
2012-03-27 10:17 914<p> </p> <h1 cla ... -
zookeeper安装和应用场合(名字,配置,锁,队列,集群管理)[转]
2012-01-12 17:59 1647安装和配置详解 本文 ... -
Jakarta-Common-BeanUtils使用笔记[转]
2012-01-10 14:13 1153Jakarta-Common-BeanUtils ... -
一个关于Java Thread wait(),notify()的实用例【转】
2012-01-07 16:05 1019///// // ProducerConsume ... -
Java基础:Java中的 assert 关键字解析【转】
2012-01-06 19:50 1056J2SE 1.4在语言上提供了 ... -
一篇不错的讲解Java异常的文章(转载)----感觉很不错,读了以后很有启发[转]
2012-01-06 15:02 1259六种异常处理的陋习 ... -
如何解决HP QC(Quality Center)在Windows 7下不能工作的问题
2011-12-26 10:48 1574HP QC(Quantity Center) 是一款不错的测 ... -
JAVA读写文件,中文乱码 【转】
2011-12-19 23:43 2115最近在做HTML静态生成,需要从硬盘上把模版文件的内容读出来。 ... -
Java 6 JVM参数选项大全(中文版)【转】
2011-12-19 19:51 966Java 6 JVM参数选项大全(中文版) 作者 ... -
使用assembly plugin实现自定义打包【转】
2011-12-13 01:58 965在上一篇文章中,讨论到在对maven的机制不熟悉的情况下,为了 ... -
使用maven ant task实现非标准打包[转]
2011-12-13 01:56 1045maven很强大,但是总有些事情干起来不是得心应手,没有使用a ... -
Java日期转换SimpleDateFormat格式大全【转】
2011-12-08 20:22 130924小时制时间 显示: public clas ... -
使用Spring的表单标签库
2011-11-22 20:08 106713.9. 使用Spring的 ...
相关推荐
### 剖析MFC多线程程序的同步机制 #### 概述 在现代软件开发中,多线程编程已成为提升程序性能的关键技术之一。然而,随着线程数量的增加,线程间的同步问题变得日益突出。MFC(Microsoft Foundation Classes)...
在Monitor Object设计模式中,参与者之间将发生如下的协作过程:同步方法的调用和串行化、同步方法线程挂起、监视条件通知和同步方法线程恢复。在这种模式中,客户线程调用监视者对象的同步方法时,必须首先获取它的...
Java 线程同步机制中 synchronized 关键字的理解 Java 的线程同步机制是为了解决多个线程共享同一片存储空间所带来的访问冲突问题。其中,synchronized 关键字是 Java 语言中解决这种冲突的重要机制。 ...
wait和notify方法是Java中最基本的同步机制,通过使用锁机制来实现异步调用转同步。下面是一个使用wait和notify方法的示例代码: ```java public class Demo1 extends BaseDemo { private final Object lock = ...
在深入探讨Java虚拟机(JVM)如何处理线程间的资源同步与交互机制之前,我们先来明确几个关键概念:线程、多线程、同步、并发以及它们在Java中的实现方式。Java作为一种广泛应用于分布式系统开发的编程语言,其内部...
4. **临界区**:临界区是指程序中可能被多个线程同时访问的关键代码区域,需要通过同步机制进行保护。 5. **同步机制**:Java通过`synchronized`关键字支持线程同步,包括同步块和同步方法。 #### 三、多线程同步...
标题中的“2 线程同步机制.md”可能涵盖了这些内容: 1. **synchronized 关键字**:Java中的`synchronized`关键字用于保证同一时间只有一个线程可以执行特定的代码块或方法,确保线程安全。它可以修饰实例方法、...
在Java编程语言中,同步代码块(synchronized blocks)是一种重要的多线程控制机制,用于保证线程安全,防止数据的不一致性。本压缩包包含了两个示例代码——Example12.java和Example13.java,它们是针对同步代码块...
这通常涉及到线程安全的数据结构和同步机制。 3. **代理(Proxy)**:客户端通过代理对象与活性对象进行交互。代理负责将方法调用转换为任务并提交到任务队列,同时提供同步原语(如future或promise)以处理结果的...
在本文中,我们将深入探讨如何使用C#编程语言与Esri的MapObject库结合,来构建一个GIS(地理信息系统)程序。MapObject是Esri公司提供的一个强大的地图开发组件,它允许开发者创建交互式地图应用,支持多种地理数据...
- **实时数据同步**:ObjectBox支持实时数据监听,当数据库中的数据发生变化时,能够立即通知到应用程序,用于实现动态UI更新。 7. **缓存与性能**: - **内存缓存**:ObjectBox有内置的内存缓存机制,能快速访问...
本主题将深入探讨如何利用同步机制来确保在Java环境中多线程操作的正确性和一致性。 一、线程安全问题 在多线程环境下,当多个线程访问共享资源时,如果没有适当的控制,可能会导致数据不一致、死锁、活锁或饥饿等...
ThreadLocal不是一种同步机制,而是设计来解决线程间数据隔离问题的工具。 ThreadLocal接口提供三个主要方法:`get()`、`initialValue()` 和 `set(Object value)`。`get()` 方法返回当前线程的ThreadLocal变量副本...
在数据库管理中,大字段通常指的是那些存储大量数据的字段,如BLOB(Binary Large Object)、TEXT、VARCHAR(MAX)等类型。这些字段在处理时可能会带来性能问题,尤其是在同步过程中。本文将深入探讨大字段的使用场景...
9. **多线程支持**:如果MapObject支持多线程应用,"common"文件夹中可能会有线程安全的代码和同步原语,以确保在并发环境下的正确性。 10. **配置和设置**:通用配置文件或设置管理代码可能在这里,用于保存和读取...
6. **反射机制**:Object类中的`getClass()`方法返回一个`Class`对象,代表了运行时的类信息。配合Java的反射API,我们可以动态地获取类的属性、方法等信息,实现动态调用和类型检查。 7. **线程同步**:`wait()`、...
2. **Objective-C语言特性**:Objective-C是在C语言的基础上扩展的,保留了C的语法结构,同时添加了消息传递机制、类和其他面向对象的特性。消息传递是Objective-C的关键,通过`[receiver message]`的方式调用方法。...
Object-C中的核心机制是消息传递。当你调用一个对象的方法时,实际上是在向对象发送一条消息。例如,`[myObject doSomething]`就是向`myObject`发送`doSomething`消息。这种设计使得代码具有很高的灵活性。 ### 3. ...