Java SE 学习笔记 第十二记

2012-08-01

1、wait():Object定义的方法,不能被重写。当一个线程调用该方法时,该线程必须拥有对象的锁,所以wait()必须包含在synchronized方法或者代码块中才能保证调用wait方法是线程拥有一个对象的锁。当线程调用wait方法后,线程会自动放弃对上锁对象的锁,并进入等待重新获得锁的状态,重新获得锁后线程将从wait之后的代码继续运行。重新获得锁的方法由其它拥有该对象锁的线程调用notify()方法。

2、notify():Object定义的方法,不能被重写,与wait配套使用,同样调用该方法的线程必须拥有该对象锁,所以notify方法也必须在synchronized方法或代码块中调用。当一个线程调用notify方法后,将会唤醒因与当前对象拥有同个锁,并调用wait方法进入等待的线程。如果存在多个wait线程,则会通过线程竞争的方法选择唤醒哪个线程。然而,并不是当前线程调用notify方法后就能立即唤醒被wait方法进入等待的线程,而是得等到向前线程结束或抛出异常而对上锁对象解锁后才能调用被wait进入等待的线程。

3、多个线程中,有一个对象的wait出现,就一定有该对象的notify出现,但是两者在数量上可能不一致。并且,wait方法前一般有一个条件判断,当条件满足时才调用wait。通常情况下,使用while包装wait,让每次线程被唤醒后都要再检查一次条件是否满足,因为在并发线程比较多的时候,线程被唤醒时,可能由于其它线程干扰导致条件改变,若不检查容易出现并发错误。

4、Thread.sleep方法也能令线程暂停,并且能指定暂停多长时间。与wait不同的是,sleep方法暂停时不会释放掉对象的锁,并且当暂时时间过去后,线程能自动被唤醒(wait需要notify方法唤醒)。因此sleep线程被唤醒时已经拥有对象的锁,所以才能继续马上继续进行(wait唤醒后还要重新等待获取到对象锁才能继续运行)。

5、由于wait和notify,线程对象多了wait阻塞状态。当线程调用了wait方法后,线程便进入wait阻塞状态,并进入等待池(wait pool),直到其他线程调用同锁对象的notify方法,线程便进入上锁阻塞状态,也就是进入锁池(look pool)。

6、线程组:一些线程的集合,一个线程被创建后不能再修改其隶属的线程组,创建一个线程时若没有指定线程组,则新线程与创建其的父线程隶属于同一个线程组。线程组比较少用到。

7、对象的浅拷贝:当对一个对象进行浅拷贝后,拷贝出来的对象会提供一套新的对象成员变量来复制接收原对象的各个成员变量值。因此,如果是原对象的原生数据类型成员变量,则直接将值复制过来,但如果是对象引用类型变量,由于对象类型引用变量的值只是个地址,所以复制过来的也是对象的对象成员地址,导致浅拷贝后对象的对象成员变量指向原对象的对象成员。一旦原对象或新对象任何一方的对象成员内的成员变量值发生改变,将会互相影响。但是,如果是对原对象或新对象任何一方的对象成员赋予另一个对象引用值的话,由于不再指向同一个对象,所以原对象和新对象之间不再互相影响。

8、对象的深拷贝:在基于对象浅拷贝的基础上,除了对象原生数据类型成员的复制方法一样之外,对于对象成员,深拷贝是重新构造一个对象成员再将新对象成员的引用赋给新对象的对象成员变量。因此,深拷贝之后,原对象和新对象的对象成员变量都不指向同一个对象,它们之间互不影响。

9、实现浅拷贝和深拷贝的方法:
    1)浅拷贝:Object类提供了clone()方法,其作用是进行浅拷贝,但由于其修饰符是protected,在外包中不可见,Java要求对需要进行拷贝的类要重写这个clone方法,并且要实现接口Cloneable(Cloneable是一个标识性接口,里面没有定义任何方法,只是声明而已,类似于serializable接口)和将方法声明修饰符改为public(对外包可见)。在重写的clone方法中要调用Object的方法(super.clone()),便可以进行浅拷贝。Object的clone浅拷贝的结果符合x.clone()!=x为true、x.clone().getClass()==x.getClass()为true、x.clone().equals(x)为true。
    2)深拷贝方法一:将需要深拷贝对象类在浅拷贝基础上,重写clone方法中调用super.clone()之后,调用每个对象成员的clone方法。因此,每个对象成员的类都要实现浅拷贝的方法,若对象成员又包含自己的对象成员,则它们也要编写浅拷贝,以此类推。
    3)深拷贝方法二:利用对象序列化和反序列化。当一个对象包含多个对象成员时需要对每个对象成员都进行拷贝会很繁琐,但是借助对象序列化和反序列化能够复制对象和它对象链上的所有内容到流上,又能将所有对象信息充流上读回来的特点,可以间接的实现深拷贝。当然,前提是对象的每个对象成员都可以序列化。(序列化要点:实现Serializable接口,利用ObjectOutputstream和ObjectInputstream包装流)。这种方法是最常用的深拷贝方法。

10、当类实现Serializable接口表明可序列化时,定义long静态成员变量serialVersionUID的作用在于:当该类对象序列化后反序列化回来时,若此类的定义已经发生改变(删除了一些成员变量或者增加了一些成员变量),如果没有定义这个serialVersionUID就会抛出Exception,无法进行序列化。而如果有定义serialVersionUID,反序列化若遇到类已经改变的情况,不会直接抛出Exception,而是查找类的serialVersionUID值是否相同,相同话就还是可以反序列化回来,对于被删除或者增加的成员将会以成员类型的默认属性赋值。可以说,serialVersionUID提供了对象向后兼容的可能。

11、IP用于确定数据包需要送达的主机位置,端口用于确定数据包需要交付给主机上哪一个程序。端口使用一个16位数字表示,范围0-65535。http协议默认使用80端口,用户程序使用的端口最好选择1024之后的端口。

12、在网络分层模型中,对等层协议之间交换的信息单元统称为PDU,下层把上层的PDU当做本层PDU的数据部分封装。

13、Java提供了对网络编程的支持,与网络编程相关的类包含在java.net包中。

14、URL:统一资源定位符的简称(Uniform Resource Locator),表示Internet上某一资源的地址,通过URL可以访问Internet上的各种网络资源。使用URL进行网络编程,不需要对协议本身有太多的了解,功能也比较弱,相对而言比较简单。一个URL主要包括协议标识符和资源名字两个部分。

15、java.net.URL类:URL类对象用于封装一个URL地址,并提供了相关URL操作方法。可以通过URL地址字符串直接创建URL对象,也可使用其它构造方法构造,如果构造失败会抛出MalfformedURLException异常。使用getProtocol(获取协议)、getHost(主机名)、getPort(端口)、getFile(文件名)、getRef(URL锚点)等方法可以获取URL对象相关属性。

16、构造一个URL对象并不等于连接了URL指向的文件,需要使用URL的openConnection()方法返回一个URLConnection对象(可能引发IOException异常),获得该URL的连接,再利用URLConnection对象的getInputStream()方法可以获取该URL指向的文件的输入流,继而通过对输入流的操作可以获取该URL指向的文件。URL类也提供了openStream()方法可返回URL对象指向文件的InputStream输入流,本质上是对以上两个方法的综合调用。

17、java.net.URLConnection类:访问远程资源属性的一般用途类。当建立了与远程服务器之间的连接后,可以在传输它到本地之前用URLConnection对象来检察远程对象的属性,只对HTTP协议的URL对象有意义。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值