动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ Java教程 ]的信息

本月文章推荐
.user itext create a word file.
.JavaMail常见问题之servlet 的 J.
.纯继承与扩展.
.charCodeAt 方法.
.正确地封装Java类.
.手把手教你使用CVS做.NET项目.
.Java十大热点问题调查揭晓.
.使用Java中的Timer和TimerTask.
.AlphaBot:对 Robocode 的创始人.
.连接PHP和 Java -- PHP/Java Bri.
.如何避免Microsoft非标准JavaSDK.
.Java与C++.
.显示一个java跳转页面.
.企业级应用中的Applet和Servlet的.
.程序员注意:Java开发最容易犯的.
.Java IO学习基础之读写文本文件.
.详细解析Java中抽象类和接口的区.
.浅析Java中Data类的应用技术.
.JAVA 深度控制 WORD.
.Java Socket编程之三.

Java如何共享资源

发表日期:2008-1-5 |



  对一种非凡的资源——对象中的内存——Java提供了内建的机制来防止它们的冲突。由于我们通常将数据元素设为从属于private(私有)类,然后只通过方法访问那些内存,所以只需将一个特定的方法设为synchronized(同步的),便可有效地防止冲突。在任何时刻,只可有一个线程调用特定对象的一个synchronized方法(尽管那个线程可以调用多个对象的同步方法)。下面列出简单的synchronized方法:
  synchronized void f() { /* ... */ }
  synchronized void g() { /* ... */ }
  每个对象都包含了一把锁(也叫作“监视器”),它自动成为对象的一部分(不必为此写任何非凡的代码)。调用任何synchronized方法时,对象就会被锁定,不可再调用那个对象的其他任何synchronized方法,除非第一个方法完成了自己的工作,并解除锁定。在上面的例子中,假如为一个对象调用f(),便不能再为同样的对象调用g(),除非f()完成并解除锁定。因此,一个特定对象的所有synchronized方法都共享着一把锁,而且这把锁能防止多个方法对通用内存同时进行写操作(比如同时有多个线程)。
  每个类也有自己的一把锁(作为类的Class对象的一部分),所以synchronized static方法可在一个类的范围内被相互间锁定起来,防止与static数据的接触。
  注重假如想保护其他某些资源不被多个线程同时访问,可以强制通过synchronized方访问那些资源。
  1. 计数器的同步
  装备了这个新要害字后,我们能够采取的方案就更灵活了:可以只为TwoCounter中的方法简单地使用synchronized要害字。下面这个例子是对前例的改版,其中加入了新的要害字:
  //: Sharing2.java
  // Using the synchronized keyWord to prevent
  // multiple Access to a particular resource.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  class TwoCounter2 extends Thread {
   private boolean started = false;
   private TextField
   t1 = new TextField(5),
   t2 = new TextField(5);
   private Label l =
   new Label("count1 == count2");
   private int count1 = 0, count2 = 0;
   public TwoCounter2(Container c) {
   Panel p = new Panel();
   p.add(t1);
   p.add(t2);
   p.add(l);
   c.add(p);
   }
   public void start() {
   if(!started) {
   started = true;
   super.start();
   }
   }
   public synchronized void run() {
   while (true) {
   t1.setText(Integer.toString(count1++));
   t2.setText(Integer.toString(count2++));
   try {
   sleep(500);
   } catch (InterruptedException e){}
   }
   }
   public synchronized void synchTest() {
   Sharing2.incrementAccess();
   if(count1 != count2)
   l.setText("Unsynched");
   }
  }
  class Watcher2 extends Thread {
   private Sharing2 p;
   public Watcher2(Sharing2 p) {
   this.p = p;
   start();
   }
   public void run() {
   while(true) {
   for(int i = 0; i < p.s.length; i++)
   p.s[i].synchTest();
   try {
   sleep(500);
   } catch (InterruptedException e){}
   }
   }
  }
  public class Sharing2 extends Applet {
   TwoCounter2[] s;
   private static int accessCount = 0;
   private static TextField aCount =
   new TextField("0", 10);
   public static void incrementAccess() {
   accessCount++;
   aCount.setText(Integer.toString(accessCount));
   }
   private Button
   start = new Button("Start"),
   observer = new Button("Observe");
   private boolean isApplet = true;
   private int numCounters = 0;
   private int numObservers = 0;
   public void init() {
   if(isApplet) {
   numCounters =
   Integer.parseInt(getParameter("size"));
   numObservers =
   Integer.parseInt(
   getParameter("observers"));
   }
   s = new TwoCounter2[numCounters];
   for(int i = 0; i < s.length; i++)
   s[i] = new TwoCounter2(this);
   Panel p = new Panel();
   start.addActionListener(new StartL());
   p.add(start);
   observer.addActionListener(new ObserverL());
   p.add(observer);
   p.add(new Label("Access Count"));
   p.add(aCount);
   add(p);
   }
   class StartL implements ActionListener {
   public void actionPerformed(ActionEvent e) {
   for(int i = 0; i < s.length; i++)
   s[i].start();
   }
   }
   class ObserverL implements ActionListener {
   public void actionPerformed(ActionEvent e) {
   for(int i = 0; i < numObservers; i++)
   new Watcher2(Sharing2.this);
   }
   }
   public static void main(String[] args) {
   Sharing2 applet = new Sharing2();
   // This isn't an applet, so set the flag and
   // prodUCe the parameter values from args:
   applet.isApplet = false;
   applet.numCounters =
   (args.length == 0 ? 5 :
   Integer.parseInt(args[0]));
   applet.numObservers =
   (args.length < 2 ? 5 :
   Integer.parseInt(args[1]));
   Frame aFrame = new Frame("Sharing2");
   aFrame.addWindowListener(
   new WindowAdapter() {
   public void windowClosing(WindowEvent e){
   System.exit(0);
   }
   });
   aFrame.add(applet, BorderLayout.CENTER);
   aFrame.setSize(350, applet.numCounters *100);
   applet.init();
   applet.start();
   aFrame.setVisible(true);
   }
  }
  我们注重到无论run()还是synchTest()都是“同步的”。假如只同步其中的一个方法,那么另一个就可以自由忽视对象的锁定,并可无碍地调用。所以必须记住一个重要的规则:对于访问某个要害共享资源的所有方法,都必须把它们设为synchronized,否则就不能正常地工作。
  现在又碰到了一个新问题。Watcher2永远都不能看到正在进行的事情,因为整个run()方法已设为“同步”。而且由于肯定要为每个对象运行run(),所以锁永远不能打开,而synchTest()永远不会得到调用。之所以能看到这一结果,是因为accessCount根本没有变化。
  为解决这个问题,我们能采取的一个办法是只将run()中的一部分代码隔离出来。想用这个办法隔离出来的那部分代码叫作“要害区域”,而且要用不同的方式来使用synchronized要害字,以设置一个要害区域。Java通过“同步块”提供对要害区域的支持;这一次,我们用synchronized要害字指出对象的锁用于对其中封闭的代码进行同步。如下所示:
  synchronized(syncObject) {
   // This code can be accessed by only
   // one thread at a time, assuming all
   // threads respect syncObject's lock
  }
  在能进入同步块之前,必须在synchObject上取得锁。假如已有其他线程取得了这把锁,块便不能进入,必须等候那把锁被释放。
  可从整个run()中删除synchronized要害字,换成用一个同步块包围两个要害行,从而完成对Sharing2例子的修改。但什么对象应作为锁来使用呢?那个对象已由synchTest()标记出来了——也就是当前对象(this)!所以修改过的run()方法象下面这个样子:
  
   public void run() {
   while (true) {
   synchronized(this) {
   t1.setText(Integer.toString(count1++));
   t2.setText(Integer.toString(count2++));
   }
   try {
   sleep(500);
   } catch (InterruptedException e){}
   }
   }
  这是必须对Sharing2.java作出的唯一修改,我们会看到尽管两个计数器永远不会脱离同步(取决于答应Watcher什么时候检查它们),但在run()执行期间,仍然向Watcher提供了足够的访问权限。
  当然,所有同步都取决于程序员是否勤奋:要访问共享资源的每一部分代码都必须封装到一个适当的同步块里。
  2. 同步的效率
  由于要为同样的数据编写两个方法,所以无论如何都不会给人留下效率很高的印象。看来似乎更好的一种做法是将所有方法都设为自动同步,并完全消除synchronized要害字(当然,含有synchronized run()的例子显示出这样做是很不通的)。但它也揭示出获取一把锁并非一种“廉价”方案——为一次方法调用付出的代价(进入和退出方法,
上一篇:资源访问的错误方法 人气:369
下一篇:为何会堵塞 人气:494
浏览全部Java的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-10-10 企业网站智能管理系统(TZIMS) v6
2008-10-10 拓文asp.net网站内容管理系统 v6
2008-10-10 动网论坛PHP版 v2.0++ Build 081
2008-10-10 免费时代CMS v5.0
2008-10-10 wodig第四季中文DIGG社区 v4.1 b
2008-10-10 老Y文章管理系统 v2.2 bulid 081
2008-10-10 魔法盒动感相册 ASP+SQL版 v2.0
2008-10-10 Asoft签到管理系统 v3.0 Pack1
2008-10-10 哥特人音乐网潮流留言本 v1.1
2008-9-29 酷狗音乐(原KuGoo)2008 v5.310 正
2008-9-29 QQTab 1.1
2008-9-29 网络传送带 Net Transport 2.64a
2008-9-29 谷歌金山词霸v1.8
2008-9-29 TweakVI 1.0 Build 1090
2008-9-29 ACDSee Pro 2.5 Build 333 汉化绿
2008-9-29 Winamp v5.541(2189) 周明波简体
2008-9-27 CCleaner 2.12.651
2008-9-27 Mozilla Thunderbird 2.0.0.17 英
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | 广告代码 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 健康查询 | 万年历 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成