服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

java多线程同步中的两个特殊类

ad_qqread_mid_big">
  我们首先开发一个busyflag的类,类似于c++中的simaphore。

public class busyflag
{
 protected thread busyflag = null;
 protected int busycount = 0;
 public synchronized void getbusyflag()
 {
  while (trygetbusyflag() == false)
  {
   try
   {
    wait();
   }
   catch (exception e) {}
  }
 }

 private synchronized boolean trygetbusyflag()
 {
  if (busyflag == null)
  {
   busyflag = thread.currentthread();
   busycount = 1;
   return true;
  }
  if (busyflag == thread.currentthread())
  {
   busycount++; return true;
  }
  return false;
 }
 
 public synchronized void freebusyflag()
 {
  if(getowner()== thread.currentthread())
  {
   busycount--;
   if(busycount==0)
   {
    busyflag = null;
    notify();
   }
  }
 }

 public synchronized thread getowner()
 {
   return busyflag;
 }
}

  注:参考scott oaks & henry wong《java thread》

  busyflag有3个公开方法:getbusyflag, freebusyflag, getowner,分别用于获取忙标志、释放忙标志和获取当前占用忙标志的线程。使用这个busyflag也非常地简单,只需要在需要锁定的地方,调用busyflag的getbusyflag(),在对锁定的资源使用完毕时,再调用改busyflag的freebusyflag()即可。下面我们开始改造前面中的account和atm类,并应用busyflag工具类使得同时只有一个线程能够访问同一个账户的目标得以实现。首先,要改造account类,在account中内置了一个busyflag对象,并通过此标志对象对account进行锁定和解锁:

import java.util.collections;
import java.util.hashmap;
import java.util.map;
class account
{
 string name;
 //float amount;
 busyflag flag = new busyflag();
 //使用一个map模拟持久存储
 static map storage = new hashmap();
 static
 {
  storage.put("john", new float(1000.0f));
  storage.put("mike", new float(800.0f));
 }

 static map accounts = collections.synchronizedmap(new hashmap());
 private account(string name)
 {
  this.name = name;
  //this.amount = ((float)storage.get(name)).floatvalue();
 }

 public synchronized static account getaccount (string name)
 {
  if (accounts.get(name) == null) accounts.put(name, new account(name));
  return (account) accounts.get(name);
 }

 public synchronized void deposit(float amt)
 {
  float amount = ((float)storage.get(name)).floatvalue();
  storage.put(name, new float(amount + amt));

 }

 public synchronized void withdraw(float amt) throws insufficientbalanceexception
 {
  float amount = ((float)storage.get(name)).floatvalue();
  if (amount >= amt) amount -= amt;
  else throw new insufficientbalanceexception();
  storage.put(name, new float(amount));
 }

 public float getbalance()
 {
  float amount = ((float)storage.get(name)).floatvalue(); return amount;
 }

 public void lock()
 {
  flag.getbusyflag();
 }

 public void unlock()
 {
  flag.freebusyflag();
 }
}

  新的account提供了两个用于锁定的方法:lock()和unlock(),供account对象的客户端在需要时锁定account和解锁account,account通过委托给busyflag来提供这个机制。另外,大家也发现了,新的account中提供了对account对象的缓存,同时去除了public的构造方法,改为使用一个静态工厂方法供用户获取account的实例,这样做也是有必要的,因为我们希望所有的atm机同时只能有一个能够对同一个account进行操作,我们在account上的锁定是对一个特定account对象进行加锁,如果多个atm同时实例化多个同一个user的account对象,那么仍然可以同时操作同一个账户。所以,要使用这种机制就必须保证account对象在系统中的唯一性,所以,这儿使用一个account的缓存,并将account的构造方法变为私有的。你也可以说,通过在account类锁上进行同步,即将account中的busyflag对象声明为static的,但这样就使同时只能有一台atm机进行操作了。这样,在一台atm机在操作时,全市其它的所有的atm机都必须等待。 >>>更多专题请看java的类  java线程专题

上一页 1 2 3 4 下一页 
相关内容:存储  os  logo  java  ie  
【收藏此页】【大 中 小】【打印】【关闭】
上一篇:从xml到java代码的数据绑定之对象
下一篇:论坛、聊天室中滤除html标记


10万个软件免费高速下载
教育教学 安全相关 游戏娱乐 源码下载 编程开发 数码软件 其它类别
网络软件 联络聊天 系统工具 媒体工具 图形图像 应用软件 行业软件
·多线程技术在vc++串口通信程序中的应
·利用vc# 创作简单的多线程组件
·vc中ftp协议实现多线程断点续传
·vc中利用ftp协议实现多线程断点续传
·vc下利用多线程实现文件的快速检索
·vb.net多线程应用
·用mfc编写多线程程序实例
·使用.net多线程技术显示实时股票信息
·vb.net多线程技术及其实现
·c#的多线程能力
 
·接口和抽象类的定义方式举例说明
·用maven制作java项目发行包
·java 基础入门 pom.xml 元素描述
·用jbuilder2007开发扩展jsf标签的插
·抽象类对象类和对象包装类
·使用java实现在文件中添加字符串
·instanceof和回调概念
·java变量的赋值与传递
·java se6调用java编译器的两种新方法
·weblogic运用db的java控件访问数据库
ad_qqread_mid_big">

  另外必须注意的一点是:account中的getaccount()方法必须同步,否则,将有可能生成多个account对象,因为可能多个线程同时到达这个方法,并监测到accounts中没有“john”的account实例,从而实例化多个john的account实例。s

  atm类只需作少量改动,在login方法中锁定account,在logout方法中解锁:

public class atm
{
 account acc;
 //作为演示,省略了密码验证
 public synchronized boolean login(string name)
 {
  if (acc != null) throw new illegalargumentexception("already logged in!");  
  acc = account.getaccount(name);
  acc.lock();
  return true;
 }

 public void deposit(float amt)
 {
  acc.deposit(amt);
 }

 public void withdraw(float amt) throws insufficientbalanceexception
 {
  acc.withdraw(amt);
 }

 public float getbalance()
 {
  return acc.getbalance();
 }

 public synchronized void logout ()
 {
  acc.unlock(); acc = null;
 }
}

  atmtester类不需要做任何修改即可同样运行,同时保证同一个account同时只能由一个atm进行操作。解决了上篇提到的多个atm同时对同一个account进行操作造成的问题。

  在最新的doug lea的util.concurrent工具包中(现处于jsr166)提供了类似的并发实用类:reentrantlock,它实现了java .util.concurrent.locks.lock接口(将在jdk1.5中发布),它的作用也类似于我们这儿的busyflag,实现机制、使用方法也相似。但这是一个工业强度的可重入锁的实现类。在reentrantlock的api文档中有它的使用示例:

lock l = ...;
l.lock();
try
{
 // access the resource protected by this lock
}
finally { l.unlock(); }
>>>更多专题请看java的类  java线程专题
上一页 1 2 3 4 
相关内容:存储  os  logo  java  ie  
【收藏此页】【大 中 小】【打印】【关闭】
上一篇:从xml到java代码的数据绑定之对象
下一篇:论坛、聊天室中滤除html标记


10万个软件免费高速下载
教育教学 安全相关 游戏娱乐 源码下载 编程开发 数码软件 其它类别
网络软件 联络聊天 系统工具 媒体工具 图形图像 应用软件 行业软件
·多线程技术在vc++串口通信程序中的应
·利用vc# 创作简单的多线程组件
·vc中ftp协议实现多线程断点续传
·vc中利用ftp协议实现多线程断点续传
·vc下利用多线程实现文件的快速检索
·vb.net多线程应用
·用mfc编写多线程程序实例
·使用.net多线程技术显示实时股票信息
·vb.net多线程技术及其实现
·c#的多线程能力
 
·接口和抽象类的定义方式举例说明
·用maven制作java项目发行包
·java 基础入门 pom.xml 元素描述
·用jbuilder2007开发扩展jsf标签的插
·抽象类对象类和对象包装类
·使用java实现在文件中添加字符串
·instanceof和回调概念
·java变量的赋值与传递
·java se6调用java编译器的两种新方法
·weblogic运用db的java控件访问数据库

扫描关注微信公众号