java基础知识总结

上传人:xgs****56 文档编号:10807130 上传时间:2020-04-15 格式:DOC 页数:175 大小:861.27KB
返回 下载 相关 举报
java基础知识总结_第1页
第1页 / 共175页
java基础知识总结_第2页
第2页 / 共175页
java基础知识总结_第3页
第3页 / 共175页
点击查看更多>>
资源描述
1.JAVA的StringBuffer类 StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。 所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。 在StringBuffer类中存在很多和String类一样的方法,这些方法在功能上和String类中的功能是完全一样的。但是有一个最显著的区别在于,对于StringBuffer对象的每次修改都会改变对象自身,这点是和String类最大的区别。 另外由于StringBuffer是线程安全的,关于线程的概念后续有专门的章节进行介绍,所以在多线程程序中也可以很方便的进行使用,但是程序的执行效率相对来说就要稍微慢一些。 1、StringBuffer对象的初始化StringBuffer对象的初始化不像String类的初始化一样,Java提供的有特殊的语法,而通常情况下一般使用构造方法进行初始化。例如: StringBuffer s = new StringBuffer();这样初始化出的StringBuffer对象是一个空的对象。如果需要创建带有内容的StringBuffer对象,则可以使用: StringBuffer s = new StringBuffer(“abc”);这样初始化出的StringBuffer对象的内容就是字符串”abc”。需要注意的是,StringBuffer和String属于不同的类型,也不能直接进行强制类型转换,下面的代码都是错误的: StringBuffer s = “abc”; /赋值类型不匹配 StringBuffer s = (StringBuffer)”abc”; /不存在继承关系,无法进行强转StringBuffer对象和String对象之间的互转的代码如下: String s = “abc”; StringBuffer sb1 = new StringBuffer(“123”); StringBuffer sb2 = new StringBuffer(s); /String转换为StringBuffer String s1 = sb1.toString(); /StringBuffer转换为String 2、StringBuffer的常用方法StringBuffer类中的方法主要偏重于对于字符串的变化,例如追加、插入和删除等,这个也是StringBuffer和String类的主要区别。a、append方法 public StringBuffer append(boolean b)该方法的作用是追加内容到当前StringBuffer对象的末尾,类似于字符串的连接。调用该方法以后,StringBuffer对象的内容也发生改变,例如: StringBuffer sb = new StringBuffer(“abc”); sb.append(true); 则对象sb的值将变成”abctrue”。使用该方法进行字符串的连接,将比String更加节约内容,例如应用于数据库SQL语句的连接,例如: StringBuffer sb = new StringBuffer(); String user = “test”; String pwd = “123”; sb.append(“select * from userInfo where username=“) .append(user) .append(“ and pwd=”) .append(pwd); 这样对象sb的值就是字符串“select * from userInfo where username=test and pwd=123”。b、deleteCharAt方法 public StringBuffer deleteCharAt(int index)该方法的作用是删除指定位置的字符,然后将剩余的内容形成新的字符串。例如: StringBuffer sb = new StringBuffer(“Test”); sb. deleteCharAt(1);该代码的作用删除字符串对象sb中索引值为1的字符,也就是删除第二个字符,剩余的内容组成一个新的字符串。所以对象sb的值变为”Tst”。还存在一个功能类似的delete方法: public StringBuffer delete(int start,int end)该方法的作用是删除指定区间以内的所有字符,包含start,不包含end索引值的区间。例如: StringBuffer sb = new StringBuffer(“TestString”); sb. delete (1,4);该代码的作用是删除索引值1(包括)到索引值4(不包括)之间的所有字符,剩余的字符形成新的字符串。则对象sb的值是”TString”。 c、insert方法 public StringBuffer insert(int offset, boolean b) 该方法的作用是在StringBuffer对象中插入内容,然后形成新的字符串。例如: StringBuffer sb = new StringBuffer(“TestString”); sb.insert(4,false);该示例代码的作用是在对象sb的索引值4的位置插入false值,形成新的字符串,则执行以后对象sb的值是”TestfalseString”。 d、reverse方法 public StringBuffer reverse()该方法的作用是将StringBuffer对象中的内容反转,然后形成新的字符串。例如: StringBuffer sb = new StringBuffer(“abc”); sb.reverse();经过反转以后,对象sb中的内容将变为”cba”。 e、setCharAt方法 public void setCharAt(int index, char ch) 该方法的作用是修改对象中索引值为index位置的字符为新的字符ch。例如: StringBuffer sb = new StringBuffer(“abc”); sb.setCharAt(1,D); 则对象sb的值将变成”aDc”。 f、trimToSize方法 public void trimToSize()该方法的作用是将StringBuffer对象的中存储空间缩小到和字符串长度一样的长度,减少空间的浪费。 总之,在实际使用时,String和StringBuffer各有优势和不足,可以根据具体的使用环境,选择对应的类型进行使用。2.Java中replace()、replaceFirst()和replaceAll()区别str.replace(str中被替换的,替换后的字符)replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是:1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串);2)replaceAll的参数是regex,即基于规则表达式的替换,比如,可以通过replaceAll(d, *)把一个字符串所有的数字字符都换成星号;相同点是都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串,如果只想替换第一次出现的,可以使用 replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的是,只替换第一次出现的字符串;另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的, 即这两者也支持字符串的操作;还有一点注意:执行了替换操作后,源字符串的内容是没有发生改变的(因为String 类是final类型的不可改写,但可以把处理得到的结果赋值).举例如下:String src = new String(ab43a2c43d);System.out.println(src.replace(3,f);=ab4f2c4fd.System.out.println(src.replace(3,f);=ab4f2c4fd.System.out.println(src.replaceAll(d,f);=abffafcffd.System.out.println(src.replaceAll(a,f);=fb43fc23d.System.out.println(src.replaceFirst(d,f);=abf32c43dSystem.out.println(src.replaceFirst(4,h);=abh32c43d.如何将字符串中的替换成:String msgIn;String msgOut;msgOut=msgIn.replaceAll(,);原因:在java中是一个转义字符,所以需要用两个代表一个。例如System.out.println( ) ;只打印出一个。但是也是正则表达式中的转义字符(replaceAll 的参数就是正则表达式),需要用两个代表一个。所以:被java转换成,又被正则表达式转换成。同样CODE: Java: Regex: 将字符串中的/替换成的几种方式:msgOut= msgIn.replaceAll(/, );msgOut= msgIn.replace(/, );3.window.location和window.open的区别window.location = http:/www.xxxxxxxx.net 跳转后有后退功能window.location.replace(http:/www.xxxxxxxx.net) 跳转后没有后退功能window.open(http:/www.xxxxxxxx.net) 要新的窗口打开链接4.Class.forName的作用以及为什么要用它【转】Posted on 2010-03-03 10:24 火之光 阅读(674) 评论(0) 编辑 收藏 Class.forName(xxx.xx.xx) 返回的是一个类首先你要明白在java里面任何class都要装载在虚拟机上才能运行。这句话就是装载类用的(和new 不一样,要分清楚)。至于什么时候用,你可以考虑一下这个问题,给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?只有你提到的这个方法了,不过要再加一点。A a = (A)Class.forName(pacage.A).newInstance();这和你A a = new A();是一样的效果。关于补充的问题答案是肯定的,jvm会执行静态代码段,你要记住一个概念,静态代码是和class绑定的,class装载成功就表示执行了你的静态代码了。而且以后不会再走这段静态代码了。Class.forName(xxx.xx.xx) 返回的是一个类Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段动态加载和创建Class 对象,比如想根据用户输入的字符串来创建对象String str = 用户输入的字符串Class t = Class.forName(str);t.newInstance(); 在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。那么为什么会有两种创建对象方式?这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。Java中工厂模式经常使用newInstance()方法来创建对象,因此从为什么要使用工厂模式上可以找到具体答案。 例如:class c = Class.forName(“Example”);factory = (ExampleInterface)c.newInstance();其中ExampleInterface是Example的接口,可以写成如下形式:String className = Example;class c = Class.forName(className);factory = (ExampleInterface)c.newInstance();进一步可以写成如下形式:String className = readfromXMlConfig;/从xml 配置文件中获得字符串class c = Class.forName(className);factory = (ExampleInterface)c.newInstance();上面代码已经不存在Example的类名称,它的优点是,无论Example类怎么变化,上述代码不变,甚至可以更换Example的兄弟类Example2 , Example3 , Example4,只要他们继承ExampleInterface就可以。从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用newInstance()方法的时候,就必须保证:1、这个类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载java API的那个加载器。现在可以看出,newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。 这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。最后用最简单的描述来区分new关键字和newInstance()方法的区别:newInstance: 弱类型。低效率。只能调用无参构造。new: 强类型。相对高效。能调用任何public构造。5.Hibernate包作用详解【转】Posted on 2009-12-23 11:32 火之光 阅读(168) 评论(0) 编辑 收藏 Hibernate一共包括了23个jar包,令人眼花缭乱。本文将详细讲解Hibernate每个jar包的作用,便于你在应用中根据自己的需要进行取舍。下载Hibernate,例如2.0.3稳定版本,解压缩,可以看到一个hibernate2.jar和lib目录下有22个jar包: hibernate2.jar:Hibernate的库,没有什么可说的,必须使用的jar包 cglib-asm.jar:CGLIB库,Hibernate用它来实现PO字节码的动态生成,非常核心的库,必须使用的jar包 dom4j.jar:dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,dom4j无论在那个方面都是非常出色的。我早在将近两年之前就开始使用dom4j,直到现在。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这是必须使用的jar包,Hibernate用它来读写配置文件。 odmg.jar:ODMG是一个ORM的规范,Hibernate实现了ODMG规范,这是一个核心的库,必须使用的jar包。 commons-collections.jar:Apache Commons包中的一个,包含了一些Apache开发的集合类,功能比java.util.*强大。必须使用的jar包。 commons-beanutils.jar:Apache Commons包中的一个,包含了一些Bean工具类类。必须使用的jar包。 commons-lang.jar:Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。 commons-logging.jar:Apache Commons包中的一个,包含了日志功能,必须使用的jar包。这个包本身包含了一个Simple Logger,但是功能很弱。在运行的时候它会先在CLASSPATH找log4j,如果有,就使用log4j,如果没有,就找JDK1.4带的java.util.logging,如果也找不到就用Simple Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾,当初Apache极力游说Sun把log4j加入JDK1.4,然而JDK1.4项目小组已经接近发布JDK1.4产品的时间了,因此拒绝了Apache的要求,使用自己的java.util.logging,这个包的功能比log4j差的很远,性能也一般。后来Apache就开发出来了commons-logging.jar用来兼容两个logger。因此用commons-logging.jar写的log程序,底层的Logger是可以切换的,你可以选择log4j,java.util.logging或者它自带的Simple Logger。不过我仍然强烈建议使用log4j,因为log4j性能很高,log输出信息时间几乎等于System.out,而处理一条log平均只需要5us。你可以在Hibernate的src目录下找到Hibernate已经为你准备好了的log4j的配置文件,你只需要到Apache 网站去下载log4j就可以了。commons-logging.jar也是必须的jar包。使用Hibernate必须的jar包就是以上的这几个,剩下的都是可选的。 ant.jar:Ant编译工具的jar包,用来编译Hibernate源代码的。如果你不准备修改和编译Hibernate源代码,那么就没有什么用,可选的jar包 optional.jar:Ant的一个辅助包。 c3p0.jar:C3PO是一个数据库连接池,Hibernate可以配置为使用C3PO连接池。如果你准备用这个连接池,就需要这个jar包。 proxool.jar:也是一个连接池,同上。 commons-pool.jar, commons-dbcp.jar:DBCP数据库连接池,Apache的Jakarta组织开发的,Tomcat4的连接池也是DBCP。实际上Hibernate自己也实现了一个非常非常简单的数据库连接池,加上上面3个,你实际上可以在Hibernate上选择4种不同的数据库连接池,选择哪一个看个人的偏好,不过DBCP可能更通用一些。另外强调一点,如果在EJB中使用Hibernate,一定要用App Server的连接池,不要用以上4种连接池,否则容器管理事务不起作用。 connector.jar:JCA规范,如果你在App Server上把Hibernate配置为Connector的话,就需要这个jar。不过实际上一般App Server肯定会带上这个包,所以实际上是多余的包。 jaas.jar:JAAS是用来进行权限验证的,已经包含在JDK1.4里面了。所以实际上是多余的包。 jcs.jar:如果你准备在Hibernate中使用JCS的话,那么必须包括它,否则就不用。 jdbc2_0-stdext.jar:JDBC2.0的扩展包,一般来说数据库连接池会用上它。不过App Server都会带上,所以也是多余的。 jta.jar:JTA规范,当Hibernate使用JTA的时候需要,不过App Server都会带上,所以也是多余的。 junit.jar:Junit包,当你运行Hibernate自带的测试代码的时候需要,否则就不用。 xalan.jar, xerces.jar, xml-apis.jar:Xerces是XML解析器,Xalan是格式化器,xml-apis实际上是JAXP。一般App Server都会带上,JDK1.4也包含了解析器,不过不是Xerces,是Crimson,效率比较差,不过Hibernate用XML只不过是读取配置文件,性能没什么紧要的,所以也是多余的。6.JAVA多线程的问题以及处理【转】Posted on 2009-12-03 17:43 火之光 阅读(603) 评论(1) 编辑 收藏 12.4多线程问题及处理 多线程编程为程序开发带来了很多的方便,但是也带来了一些问题,这些问题是在程序开发过程中必须进行处理的问题。 这些问题的核心是,如果多个线程同时访问一个资源,例如变量、文件等,时如何保证访问安全的问题。在多线程编程中,这种会被多个线程同时访问的资源叫做临界资源。 下面通过一个简单的示例,演示多个线程访问临界资源时产生的问题。在该示例中,启动了两个线程类DataThread的对象,该线程每隔200毫秒输出一次变量n的值,并将n的值减少1。变量n的值存储在模拟临界资源的Data类中,该示例的核心是两个线程类都使用同一个Data类的对象,这样Data类的这个对象就是一个临界资源了。示例代码如下: package syn1;/* *模拟临界资源的类 */public class Data public int n; public Data() n = 60; package syn1;/* *测试多线程访问时的问题 */public class TestMulThread1 public static void main(String args) Data data = new Data(); DataThread d1 = new DataThread(data,线程1); DataThread d2 = new DataThread(data,线程2); package syn1;/* *访问数据的线程 */public class DataThread extends Thread Data data; String name; public DataThread(Data data,String name) this.data = data; this.name = name; start(); public void run() try for(int i = 0;i 10;i+) System.out.println(name + : + data.n); data.n-; Thread.sleep(200); catch(Exception e) 在运行时,因为不同情况下该程序的运行结果会出现不同,该程序的一种执行结果为: 线程1:60线程2:60线程2:58线程1:58线程2:56线程1:56线程2:54线程1:54线程2:52线程1:52线程2:50线程1:50线程2:48线程1:48线程2:47线程1:46线程2:44线程1:44线程2:42线程1:42 从执行结果来看,第一次都输出60是可以理解的,因为线程在执行时首先输出变量的值,这个时候变量n的值还是初始值60,而后续的输出就比较麻烦了,在开始的时候两个变量保持一致的输出,而不是依次输出n的每个值的内容,而到将要结束时,线程2输出47这个中间数值。 出现这种结果的原因很简单:线程1改变了变量n的值以后,还没有来得及输出,这个变量n的值就被线程2给改变了,所以在输出时看的输出都是跳跃的,偶尔出现了连续。 出现这个问题也比较容易接受,因为最基本的多线程程序,系统只保证线程同时执行,至于哪个先执行,哪个后执行,或者执行中会出现一个线程执行到一半,就把CPU的执行权交给了另外一个线程,这样线程的执行顺序是随机的,不受控制的。所以会出现上面的结果。 这种结果在很多实际应用中是不能被接受的,例如银行的应用,两个人同时取一个账户的存款,一个使用存折、一个使用卡,这样访问账户的金额就会出现问题。或者是售票系统中,如果也这样就出现有人买到相同座位的票,而有些座位的票却未售出。 在多线程编程中,这个是一个典型的临界资源问题,解决这个问题最基本,最简单的思路就是使用同步关键字synchronized。 synchronized关键字是一个修饰符,可以修饰方法或代码块,其的作用就是,对于同一个对象(不是一个类的不同对象), 当多个线程都同时调用该方法或代码块时,必须依次执行,也就是说,如果两个或两个以上的线程同时执行该段代码时,如果一个线程已经开始执行该段代码,则另 外一个线程必须等待这个线程执行完这段代码才能开始执行。就和在银行的柜台办理业务一样,营业员就是这个对象,每个顾客就好比线程,当一个顾客开始办理 时,其它顾客都必须等待,及时这个正在办理的顾客在办理过程中接了一个电话 (类比于这个线程释放了占用CPU的时间,而处于阻塞状态),其它线程也只能等待。 使用synchronized关键字修改以后的上面的代码为: package syn2;/* *模拟临界资源的类 */public class Data2 public int n; public Data2() n = 60; public synchronized void action(String name) System.out.println(name + : + n); n-; package syn2;/* *测试多线程访问时的问题 */public class TestMulThread2 public static void main(String args) Data2 data = new Data2(); Data2Thread d1 = new Data2Thread(data,线程1); Data2Thread d2 = new Data2Thread(data,线程2); package syn2;/* *访问数据的线程 */public class Data2Thread extends Thread Data2 data; String name; public Data2Thread(Data2 data,String name) this.data = data; this.name = name; start(); public void run() try for(int i = 0;i 10;i+) data.action(name); Thread.sleep(200); catch(Exception e) 该示例代码的执行结果会出现不同,一种执行结果为: 线程1:60线程2:59线程2:58线程1:57线程2:56线程1:55线程2:54线程1:53线程2:52线程1:51线程2:50线程1:49线程1:48线程2:47线程2:46线程1:45线程2:44线程1:43线程2:42线程1:41 在该示例中,将打印变量n的代码和变量n变化的代码组成一个专门的方法action,并且使用修饰符synchronized修改该方法,也就是说对于一个Data2的对象,无论多少个线程同时调用action方法时,只有一个线程完全执行完该方法以后,别的线程才能够执行该方法。这就相当于一个线程执行到该对象的synchronized方法时,就为这个对象加上了一把锁,锁住了这个对象,别的线程在调用该方法时,发现了这把锁以后就继续等待下去了。如果这个例子还不能帮助你理解如何解决多线程的问题,那么下面再来看一个更加实际的例子卫生间问题。 例 如火车上车厢的卫生间,为了简单,这里只模拟一个卫生间,这个卫生间会被多个人同时使用,在实际使用时,当一个人进入卫生间时则会把卫生间锁上,等出来时 打开门,下一个人进去把门锁上,如果有一个人在卫生间内部则别人的人发现门是锁的则只能在外面等待。从编程的角度来看,这里的每个人都可以看作是一个线程 对象,而这个卫生间对象由于被多个线程访问,则就是临界资源,在一个线程实际使用时,使用synchronized关键将临界资源锁定,当结束时,释放锁定。实现的代码如下: package syn3;/* *测试类 */public class TestHuman public static void main(String args) Toilet t = new Toilet(); /卫生间对象 Human h1 = new Human(1,t); Human h2 = new Human(2,t); Human h3 = new Human(3,t); package syn3;/* *人线程类,演示互斥 */public class Human extends Thread Toilet t; String name; public Human(String name,Toilet t) this.name = name; this.t = t; start(); /启动线程 public void run() /进入卫生间 t.enter(name); package syn3;/* *卫生间,互斥的演示 */public class Toilet public synchronized void enter(String name) System.out.println(name + 已进入!); try Thread.sleep(2000); catch(Exception e) System.out.println(name + 离开!); 该示例的执行结果为,不同次数下执行结果会有所不同: 1已进入!1离开!3已进入!3离开!2已进入!2离开! 在该示例代码中,Toilet类表示卫生间类,Human类模拟人,是该示例中的线程类,TestHuman类是测试类,用于启动线程。在TestHuman中,首先创建一个Toilet类型的对象t,并将该对象传递到后续创建的线程对象中,这样后续的线程对象就使用同一个Toilet对象,该对象就成为了临界资源。下面创建了三个Human类型的线程对象,每个线程具有自己的名称name参数,模拟3个线程,在每个线程对象中,只是调用对象t中的enter方法,模拟进入卫生间的动作,在enter方法中,在进入时输出调用该方法的线程进入,然后延迟2秒,输出该线程离开,然后后续的一个线程进入,直到三个线程都完成enter方法则程序结束。 在该示例中,同一个Toilet类的对象t的enter方法由于具有synchronized修饰符修饰,则在多个线程同时调用该方法时,如果一个线程进入到enter方法内部,则为对象t上锁,直到enter方法结束以后释放对该对象的锁定,通过这种方式实现无论多少个Human类型的线程,对于同一个对象t,任何时候只能有一个线程执行enter方法,这就是解决多线程问题的第一种思路互斥的解决原理。12.4.2同步 使用互斥解决多线程问题是一种简单有效的解决办法,但是由于该方法比较简单,所以只能解决一些基本的问题,对于复杂的问题就无法解决了。 解 决多线程问题的另外一种思路是同步。同步是另外一种解决问题的思路,结合前面卫生间的示例,互斥方式解决多线程的原理是,当一个人进入到卫生间内部时,别 的人只能在外部时刻等待,这样就相当于别的人虽然没有事情做,但是还是要占用别的人的时间,浪费系统的执行资源。而同步解决问题的原理是,如果一个人进入 到卫生间内部时,则别的人可以去睡觉,不占用系统资源,而当这个人从卫生间出来以后,把这个睡觉的人叫醒,则它就可以使用临界资源了。所以使用同步的思路 解决多线程问题更加有效,更加节约系统的资源。 在常见的多线程问题解决中,同步问题的典型示例是“生产者-消费者”模型,也就是生产者线程只负责生产,消费者线程只负责消费,在消费者发现无内容可消费时则睡觉。下面举一个比较实际的例子生活费问题。 生 活费问题是这样的:学生每月都需要生活费,家长一次预存一段时间的生活费,家长和学生使用统一的一个帐号,在学生每次取帐号中一部分钱,直到帐号中没钱时 通知家长存钱,而家长看到帐户还有钱则不存钱,直到帐户没钱时才存钱。在这个例子中,这个帐号被学生和家长两个线程同时访问,则帐号就是临界资源,两个线 程是同时执行的,当每个线程发现不符合要求时则等待,并释放分配给自己的CPU执行时间,也就是不占用系统资源。实现该示例的代码为: package syn4;/* *测试类 */public class TestAccount public static void main(String args) Accout a = new Accout(); StudentThread s = new StudentThread(a); GenearchThread g = new GenearchThread(a); package syn4;/* *模拟学生线程 */public class StudentThread extends Thread Accout a; public StudentThread(Accout a) this.a = a; start(); public void run() try while(true) Thread.sleep(2000); a.getMoney(); /取钱 catch(Exception e) package syn4;/* *家长线程 */public class GenearchThread extends Thread Accout a; public GenearchThread(Accout a) this.a = a; start(); public void run() try while(true) Thread.sleep(12000); a.saveMoney(); /存钱 catch(Exception e) package syn4;/* *银行账户 */public class Accout int money = 0; /* *取钱 *如果账户没钱则等待,否则取出所有钱提醒存钱 */ public synchronized void getMoney() System.out.println(准备取钱!); try if(money = 0) wait(); /等待 /取所有钱 System.out.println(剩余: + money); money -= 50; /提醒存钱 notify(); catch(Exception e) /* *存钱 *如果有钱则等待,否则存入200提醒取钱 */ public synchronized void saveMoney() System.out.println(准备存钱!); try if(money != 0) wait(); /等待 /取所有钱 money = 200; System.out.println(存入: + money); /提醒存钱 notify(); catch(Exception e) 该程序的一部分执行结果为: 准备取钱!准备存钱!存入:200剩余:200准备取钱!剩余:150准备取钱!剩余:100准备取钱!剩余:50准备取钱!准备存钱!存入:200剩余:200准备取钱!剩余:150准备取钱!剩余:100准备取钱!剩余:50准备取钱! 在该示例代码中,TestAccount类是测试类,主要实现创建帐户Account类的对象,以及启动学生线程StudentThread和启动家长线程GenearchThread。在StudentThread线程中,执行的功能是每隔2秒中取一次钱,每次取50元。在GenearchThread线程中
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 解决方案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!