A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

11线程之间通信的理解
其实,Java提供了3个非常重要的方法来巧妙地解决线程间的通信问题。
这3个方法分别是:wait()、notify()和notifyAll()。
它们都是Object类的最终方法,因此每一个类都默认拥有它们。
虽然所有的类都默认拥有这3个方法,但是只有在synchronized关键字作用的范围内,并且是同一个同步问题中搭配使用这3个方法时才有实际的意义。
这些方法在Object类中声明的语法格式如下所示:
         final void wait() hrows InterruptedException   
         final void notify()
         final void notifyAll()
调用wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行态退出,进入等待队列,直到被再次唤醒。
调用notify()方法可以唤醒等待队列中第一个等待同一共享资源的线程,并使该线程退出等待队列,进入可运行态。
调用notifyAll()方法可以使所有正在等待队列中等待同一共享资源的线程从等待状态退出,进入可运行状态,此时,优先级最高的那个线程最先执行。
显然,利用这些方法就不必再循环检测共享资源的状态,而是在需要的时候直接唤醒等待队列中的线程就可以了。这样不但节省了宝贵的CPU资源,也提高了程序的效率。
由于wait()方法在声明的时候被声明为抛出InterruptedException异常,因此,在调用wait()方法时,需要将它放入try…catch代码块中。此外,使用该方法时还需要把它放到一个同步代码段中,否则会出现如下异常:
"java.lang.IllegalMonitorStateException: current thread not owner"

12线程的状态
线程的五种状态:
1)新建(new) 用new语句创建的线程对处于新建状态,此时它和其它Java对象一样,仅仅在Heap中被分配了内存。当一个线程处于新建状态时,它仅仅是一个空的线程对象,系统不为它分配资源。 Thread t = new Thread(new Runner());
2)就绪(Runnable) 程序通过线程对象调用启动方法start()后,系统会为这个线程分配它运行时所需的除处理器之外的所有系统资源。这时,它处在随时可以运行的状态,在随后的任意时刻,只要它获得处理器即会进入运行状态。 t.start()
3)运行(Running) 处于这个状态的线程占用CPU,执行程序代码。在并发环境中,如果计算机只有一个CPU,那么任何时刻只会有一个线程处于这个状态。如果计算机中有多个CPU,那么同一时刻可以让几个线程占用不同的CPU,使它们都处于运行状态,只有处于就绪状态的线程才有机会转到运行状态。
4)阻塞(Blocked) 阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才有机会转到运行状态。
阻塞状态可分为以下3种:
         位于对象等待池中的阻塞状态(Blocked in object's wait pool):当线程处于运行状态时,如果执行了某个对象的wait()方法,Java虚拟机就会把线程放到这个对象的等待池中。
         位于对象锁池中的阻塞状态(Blocked in object's lock pool):当线程处于运行状态,试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他线程占用,Java虚拟机就会把这个线程放到这个对象的锁池中。
         其他阻塞状态(Otherwise Blocked):当前线程执行了sleep()方法,或者调用了其他线程的join()方法,或者发出了I/O请求时,就会进入这个状态。当一个线程执行System.out.println()或者System.in.read()方法时是,就会发出一个I/O请求,该线程放弃CPU,进入阻塞状态,直到I/O处理完毕,该线程才会恢复执行。
5)死亡(Dead) 当线程退出run()方法时,就进入死亡状态,该线程结束生命周期。线程有可能是正常执行完run()方法而退出,也有可能是遇到异常而退出。不管线程是正常结束还是异常结束,都不会对其他线程造成影响。

13. 数组和集合
1)数组是静态的,一个数组实例具有固定的大小,一旦创建了就无法改变容量了。而集合是可以动态扩展容量,可以根据需要动态改变大小,集合提供更多的成员方法,能满足更多的需求。
2)数组要声明元素的类型,集合类的元素类型却是object。
数组转成集合注意事项:
1.不能使用集合的增删方法。因为数组长度不能改变,其它方法可以使用;
2.如果数组中的元素是引用数据类型,转成集合时,数组元素直接作为集合的元素;如果数组中的元素是基本数据类型,转成集合时,会将数组作为集合中的元素。

14、String、StringBuffer和StringBuilder
1)在执行速度方面的比较:StringBuilder >  StringBuffer  
2)StringBuffer与StringBuilder,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,不像String一样创建一些对象进行操作,所以速度就快了。
3)StringBuilder:线程非安全的,是线程不同步的(JDK1.5后出现)
StringBuffer:线程安全的,是线程同步的
    4.什么时候使用字符串缓冲区:数据多,个数无所谓确定,类型无所谓确定,只要最后都转变成字符串,就用字符串缓冲区。
对于三者使用的总结:
1)如果要操作少量的数据用 String
2)单线程操作字符串缓冲区 下操作大量数据  StringBuilder
3)多线程操作字符串缓冲区 下操作大量数据  StringBuffer(多线程中通常不建议使用StringBuffer,最好使用StringBuilder然后自己加同步)

15.集合
集合名称阅读技巧:
JDK1.2出现的集合框架中常用的子类对象
前缀名是结构名,后缀名是体系名。
ArrayList:数组结构,看到Array就知道查询速度快,看到List就知道可以又重复元素,可以增删改查
LinkedList:链表结构,增删快
HashSet:哈希结构,查询速度更快,不保证有序,不可以重复,必须覆盖hashCode和equals方法
LinkedHashSet:链表加哈希结构,可以实现有序
TreSet:二叉树结构,可以排序。有两种方法:1.自然排序compable,2.比较器 comparator
     Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。

Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且和当前comparator的排序结果是相同的时候,这个方法才返回true.
ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,允许直接按序号索引元素. 但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,
Vector由于使用了synchronized 方法(线程安全),通常性能上较ArrayList 差,Vector属于遗留容器,现在已经不推荐使用,
LinkedList 使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,其实对内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
由于ArrayList和LinkedListed都是非线程安全的,如果需要多个线程操作同一个容器,可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这其实是装潢模式最好的例子,将已有对象传入另一个类的构造器中创建新的对象来增加新功能)。
Map集
Map(k,v) k:此映射所维护的键的类型 v:映射值的类型
Map集合:双例集合,一次存一对,称为键值对。要保证键的唯一性。
Map集合没有迭代器,必须先将map集合转成set集合,在使用迭代器,就可以取出结合中的元素;或者使用map集合特有的entrySet方法,也可以取出map集合中虽有元素。
Map集合常见子类:
1.HashTable:哈希表结构,同步的,不允许null键,null值;
  2.HashMap:哈希表结构,不同步,允许null键,null值;
3.TreeMap:二叉树结构,不同步,可以对map集合众多键进行排序。

16.为什么需要配置path,什么时候需要classpath?
答:path路径:是操作系统的环境变量,目的是希望在任意目录下都能执行该命令操作起来更加方便快捷;
classpath是给类提供路径:想在其他目录下执行java程序时需要配置classpath路径。

17.IO流
   输入流:InputStream   输出流:OutputStream
   字节输入流:FileInputStream   字节输出流:FileOutoutStream
   字节输入流缓冲区:BufferedInputStream   字节输出流缓冲区: BufferedOutputStream
字符输入流:InputStreamReader   字符输出流:OutputStreamWriter
转换流:FileReader FileWriter
字符输入流缓冲区:BufferedReader  字符输出流缓冲区:BufferedWriter

18.OSI参考模型
  一共7层:1.物理层;2.数据化链路层;3.网络层;4.传输层;5.会话层;6.表示层;7.应用层
   物理层:定义物理设备标准,作用:传输比特流。这一层的数据叫做比特;
   数据化链路层:接受物理层的数据对MAC地址(网卡地址)进行封装与解封装,工作设备:交换机,这一层的数据叫做帧;
网络层:对下面接受的数据进行IP地址的封装与解封装,工作设备:路由器,这一层的数据叫做数据包;
传输层:定义一些数据协议和端口号,对下面接收的数据进行分段和传输,到达目的后进行重组,这一层的数据叫做段;
会话层:通过传输层建立数据传输的通路;
表示层:对接收的解释进行加密和解密,封装和解封装;
应用层:终端应用,FTP(各种文件下载)。
TCP(传输控制协议):传输效率低,可靠性高,用于操作可靠性要求高,数据量小的数据;
UDP(用户数据协议):传输效率高,可靠性低,用于操作可靠性要求低,数据量大的数据。

19.abstract与哪些关键字不能共存为什么
        final:1.被final修饰的类不可以有子类;2.被final修饰的方法不可以被覆盖;
private:1.成员方法私有化,子类不能访问;2.private私有化的,不可以被覆盖
static:被static修饰的方法,可以直接通过类名方式调用,但调用抽象方法没有意义
20. static的特点
      1.被静态修饰的成员,可以直接通过类名方式调用;2.静态成员优先与对象存在;3.静态成员随着累的加载而出现
      注意事项:
     1.静态只能访问静态;2.静态方法中不能出现this和super关键字;3.主函数是静态函数
21.wait()和sleep()的区别
1. wait()是object类中的方法,可以指定时间,也可以不指定时间;sleep()是Thread类中的方法,必须指定时间;
2. wait()释放资源,释放锁;sleep()释放资源,不释放锁。
22.网络编程的三要素
        (1)IP:网络中设备的标识
(2)端口:用于标识设备中接收数据的网络应用程序具体是哪一个,有效端口0~65535,0~1024为系统端口及保留端口
        (3)传输协议:UDP和TCP协议,信息通讯的规则
23.什么是多态,多态的好处和弊端
        多态可以理解为事物存在的多种体现形态。父类的引用指向了自己的子类对象;父类的引用也可以接收自己子类的对象。
        好处:提高了代码的扩展性
        弊端:父类的引用只能访问父类中有的成员(父类引用无法调用子类中特有的方法)
24.什么是暴力反射
        我们知道java的特性之一就是封装,将对象的属性和具体实现隐藏起来,只对外提供公共方法访问,private修饰的内部属性和方法对我们是不可见的。
        我们通过正常的方法是无法获取以及修改的,可是通过反射却可以强制获取并做一些修改,这就破坏了封装性,这就是所谓的暴力反射
25.反射获取字节码对象方式、创建对象的两种方式
        获取字节码方式三种:
        (1)类名.class,例如:System.class
        (2)对象.getClass(),例如:new Date().getClass();
        (3)Class.forName("类名"),例如:Class.forName("java.util.Date");
        创建对象的两种方式:
        (1)直接用字节码创建对象,只能调用默认的构造方法:字节码.newInstance();
        (2)获取构造方法Constructor,然后调用构造方法创建,可以通过参数不同调用不同的构造方式
26.怎么理解反射,反射的应用
        反射就是把Java类中的各种成分映射成相应的Java类。
        一般情况下我们要解决某个问题,先找到相关的类,创建该类的对象,然后通过该对象调用对应的方法来解决问题。
        反射是一个正好相反的过程,开始可能并没有类可以解决这个问题,却先用一个当时可能并不存在的方法解决了这个问题,后来才有的这个类。
        这其实就是框架的原理,先有的框架再有解决问题的类。框架描述了整体,制订了功能方法的规范。这些都需要靠反射来完成。
        使用框架有良好的扩展性,某部分功能的优化不需要涉及程序整体,只需要修改特定的部分就好了,然后通过配置文件,获取对应的类名,就可以了。
27.同步函数与同步代码块
        它们的作用都是封装多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可参与进来。
        同步代码块:位置比较灵活,多个线程中只有持有锁的才可以操作共享数据,需要指定一个对象作为锁
        同步方法:声明方法时加synchronized关键字修饰,同步函数使用的锁是this,持有锁的线程调用这个方法时其他线程无法调用。

3 个回复

倒序浏览
回复 使用道具 举报
回复 使用道具 举报
留着看看.
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马