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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 郑飞 高级黑马   /  2014-10-21 02:24  /  3470 人查看  /  28 人回复  /   5 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 郑飞 于 2014-10-24 06:56 编辑

这两天会陆续发一些比较重要的章节总结笔记,为面试做准备;(多线程,集合,集合工具;;;(3楼泛型,线程池(高新2))
因为主要是为自己准备的,所以有些烂透的东西,不做记录,语言尽量简洁;
很多地方都是个人的理解,不是视频中或别人笔记中copy,包括用词习惯等等;
总之个性的东西,只能说仅供参考,欢迎意见和纠错,照顾不到所有人胃口难免的;
---------------------------------------------------->
多线程总结
        进程:应用程序 线程:控制单元 例子:多线程(服务器300K,A单线程,B双线程,300/(1+2)=100,A100K,B200K);
        存在理由:切换(软件),快速执行(硬件),实现同时运行的效果;
        区别:其实就是应用程序和控制单元的区别,进程独立空间,线程栈独立,堆共享;
        创建:1.继承Thread重写run 2:传入Runnable子类重写run 区别:Runnable操作的数据是传入子类中的 Thread子类操作数据是本身,前者更适用于共享数据的操作;
        状态:
                1.创建new
                2:运行start()
                3:冻结wait()sleep();
                4:消亡 run运行结束 当处于冻结无法控制停止时 使用Interrupt清除冻结 恢复到阻塞 然后控制停止
                5:阻塞 被切换 清醒瞬间 创建瞬间
        控制:
                1:上面的第3,4点,常规;
                2:join 在A线程中使用B的join 效果是:A立马冻结 把本属于A的执行权给B 等B结束才恢复A的运行 注:其他线程该怎么运行还是造就;
                3:守护线程 setDaemon(true) 在start之前; 效果:当非守护都消亡后,守护自动消亡(后台线程)
                4:yield 让当前线程等待 注:不是进入阻塞,所以有可能刚等待的线程,有抢到资源继续执行;
        安全:当数据共享操作时,要加锁,否则可能操作到其他线程操作一半的数据,出现重大问题;
        解决:
                1.synchronize代码块
                2.synchronized方法
                3.ReentrantLock类对象的显式锁,可配多个Condition对象,对锁实现选择性控制;
        代码:共享数据间隔操作
<-------------------------------------------------------
类似以上这种,相当精简了,基本需要每个词自己去扩展内容,相信对某些人有用处;
--------------------------------------------------------->
集合1
        *Collection:

        存在理由:对象用来封装数据,集合用来存对象;同时弥补数组的不足之处;
        区别:可变长度,同一容器对于不同类对象的存放,操作性强(API);
        多分支:存储方式(数据结构)的不同(为了实现各分支个性存储和操作);
        API:
                增:add(),addAll(Collection);
                删:clear();remove();removeAll(Collection);
                改:retainAll(Collection)取交集;toArray();
                查:iterator();contains()containsAll(Collection);isEmpty();size();

        *Collection-List:(后面分支都这样表示,不做缩进,上级共性不再提了)

        特点:有序(存取顺序相同),可以重复.(索引)
        增:add(index);add(index,Colletion);
        删:remove(index);
        改:set(index,Object);subList(fromIndex,toIndex);
        查:get(index);indexOf(Object);lastIndextOf();firstIndextOf();
        listIterator();除Iterator中有的remove()外,增加了add(),set();和倒序迭代hasPrevious(),previous();previousIndex();

        *ArrayList:数组,不同步,改查快增删慢;长度默认10,50%增长;
        *LinkedList:链表,不同步,增删快,改查慢;
                特点:添addFirst();取getFirst();取删removeFirst()可控存取顺序
                        先进后出:(像日常生活中的瓶子);
                        后进先出:(像日常生活中的管子);
                        模拟堆栈或队列数据结构:新建类,构造对象时new个LinkedList,用其LinkedList的存取方法重新写自己的存入取出方法
                get和remove会抛出NoSuchElementException;
                1.6后pullFirst替removeFirst,peekFirst替getFirst;offerFirst替addFirst(不抛异常,返回布尔值)        
        *Vector:数组结构,同步,增删改查都很慢;长度默认10,100%增长;
                特点:1.0的时候枚举迭代方式(其他方式一样可以用)
                        for(Enumeration e = v.elements();e.hasMoreElements();)
                                    System.out.println(e.nextElement());
                这种方法现在只用在properties中
        Vector1.0出现的,集合框架1.2出现的
        Collections有方法可以得到线程安全的ArrayList对象;所以即使Vector同步,由于效率低照样被取代了;
                static List synchronizedList(List list) 返回同步list。

        *Collection-Set:
        特点:无序(存入取出顺序不同),不可重复.(无索引),功能和Collection是一致的;
        Set判断相等用equals,而不是==。返回true,Set集合是不会接受第二个对象。

        *HashSet:HashTable数据结构; 不同步;允许null;
        特点:判断相等先hashCode,再equals(hashCode可以做到完全不一样,为什么还重写equals,感兴趣的可以关注下)
        注:hash算法的功能:主要提高检索速度(大概意思张老师提过);
        应该尽量保证两个对象通过equals比较返回true时,他们的hashCode返回也相等。

        *TreeSet有序存放:二叉树;对存入元素排序;(所以存入之前必须可以比较)
                1.实现Comparable接口重写compareTo方法;
                2.构造TreeSet的时候传入一个比较器自定义比较器(实现Comparator接口);
                3.两种都存在的时候,以比较器为主;
        注:也可以实现堆栈和队列效果,控制compareTo的结果;
        Comparator comparator():返回当前Set使用的Comparator,若返回null,表示以自然顺序排序。
        first() 返回第一个元素。 last() 返回最后一个元素。
        有部分API相关到其父接口 SortedSet,可以看看;
<---------------------------------------------------------------
---------------------------------------------------------------->

集合2
        *Map
        特点:
                键值对,key不重复,对应唯一的value(注:value能重复,但1key只对1value)
                Map里的key集存储方式和对应的Set集合中的元素存储方式一致
                Map.Entry内部接口,保存key-value;
        共性方法:(基本字面就能理解,记不住就是用少了.)
                clear();containsKey(Object key);containsValue(Object  value);isEmpty();entrySet();keySet();
                put();返回被覆盖的value;putAll(Map m);remove(Object key);size();Collection values():
        *Map.Entry

        Entry是Map接口里面的一个内部接口.
                该接口用于封装key- value,有3个方法:getKey();getValue();setValue(Object value)返回旧value;
        
        迭代:(注:嵌套泛型归到泛型)
                1.entrySet(),取出entry集,然后遍历,同时取出key和value;
                2.keySet(),取出key集,遍历,同时取出value
        *HashTable:哈希表,键值对非空,同步;
        *HashMap:哈希表,与HashTable的区别:允许空键值对,非同步;
        *TreeMap:二叉树,非同步,可对键排序;
<----------------------------------------------------------
---------------------------------------------------------->
集合3
        *工具类
        *Collections
        reverse(List list):反转顺序;shuffle(List list):随机排序;sort(List list):自然升序排序;swap(List list,int i, int j):元素交换;
        rotate(List list, int distance):[a, b, c, d, e]执行Collections.rotate(l.subList(1, 4), -1);后结果:[a, c, d, b, e](建议查API)
        binarySearch(List list, Object key) 二分搜索获得指定对象,必须先调用 Collections.sort(List list)(完成自然排序);
        max(Collection coll) 根据自然顺序,返回最大元素。min(Collection coll)返回最小元素。fill(List list, Object obj)用obj完全填充所有位置。
        frequency(Collection c, Object o)  返回等于指定对象的元素个数。
        indexOfSubList(List source, List target) 返回第一次出现的起始位置,如果没有则返回 -1。对应的last方法:lastIndexOfSubList(List source, List target)
        replaceAll(List list, Object oldVal, Object newVal)  使用另一个值替换所有某一指定值。
        *Arrays

        List asList(Object... a)返回的是不可变的List(长度固定)。注:不能增删;这个方法和Collection.toArray()方法充当了数组与collection之间的桥梁。
        例子:List<String> list= Arrays.asList("A", "B", "C");可变参数"A", "B", "C",同数组,此数组被转成固定长度的list;
        其他方法都是对基本类型数组转成list后的常规操作方法,看API;
<----------------------------------------------------------

评分

参与人数 1技术分 +2 收起 理由
杨佳名 + 2 很给力!

查看全部评分

28 个回复

倒序浏览
先来占个楼。。。飞哥依然那么晚睡

点评

三点多才睡?  发表于 2014-10-22 18:31
回复 使用道具 举报
本帖最后由 郑飞 于 2014-10-24 08:57 编辑
戏言丶 发表于 2014-10-21 03:14
先来占个楼。。。飞哥依然那么晚睡

.......还有活人:o
1楼放不下了 这里接着
----------------------------------------------------------->
泛型
        存在理由:解决类型安全,免去强制转换;
        格式:<类型>
        注:重写equals不能用,=左右泛型必须一样
        使用:
                泛型类(要操作引用类型不确定又想要扩展,早期用Object,现在用泛型),
                泛型类结合泛型方法使用:类上定义一个,部分方法上再定义另一个;
        例子:
                泛型类和泛型方法综合使用,就这个例子够了;接口上使用泛型,没什么特殊的不写了;
        class Test<T> //类泛型定义在类名后
        {
                //方法泛型定义在返回值前
                public <I>void method(T t,I i)//类泛型和方法自定义泛型在同一个方法中
                {
                        System.out.println(t);
                        System.out.println(i);
                        //System.out.println(t+i);//不能这么用泛型局限性
                }
                public static void main(String[] args)
                {
                        new Test().method("abc",100);
                        new Test().method(120,"bc");
                }
        }        
        限定:
                <?>和<T>的区别,方法体中可以存在T t =....;而 ? 没这个用法;
                ? super E; ? extends E; 多看视频,类似这种东西掌握后就不会再变,越早掌握越好.别人提过的就不写了,除此之外真不知道该怎么总结;
        嵌套:
                Map迭代<Entry<Integer, String>>
<-------------------------------------------------------
线程并发库(其实是高新部分,不含空中网):        
        存在理由:
                Tcp服务端例子,大量用户不断的访问和消亡,致使普通多线程必须不断新建和销毁线程,极其影响服务器性能.所以引入线程池原理;
                把任务交给线程池处理,池中的线程运行完手上的任务后不销毁,处于空闲等待任务状态.提高了服务器性能.
        种类:
                固定线程池 ExecutorService threadPool=Executors.newFixedThreadPool(5) 固定为5个线程;
                缓存线程池 newCachedThreadPool();有多少任务就有多少线程 当任务减少 超时一定时间后 线程也会减少;
                单一线程池 newSingleThreadExecutor();不同于单线程,它有固定线程池的特性,保持线程数量(该线程死亡后重新恢复一个线程);
               
        关闭线程池:
                pool.shutdown()(池中无任务就关闭池)和shutdownNow()(调用该方法后,当前任务结束后关闭线程池)
        线程池定时器:
                new RunnableSchedulePool(int i).schedule(runnable,多久后运行,时间单位)
                new RunnableSchedulePool(int i).scheduleAtFixedRate()(runnable,多久后运行,间隔时间,时间单位)
        读写锁妙用:嵌套读写锁,实现对象缓存系统高效访问;
        Semaphere同步工具:
                规定N个线程同时访问,多了就进不去;实际上就是一个升级的锁;        
                原来的锁一般控制单线程在操作资源,而Semaphere锁,能判断当前进持有该锁的线程数量,控制固定数量线程的访问;
        CyclicBarrier同步工具:
                规定N个线程,都执行到cb.await()的时候,才全体运
                运用环境:多线程起点终点一样,运行速度不一样;(日常集体出游例子);
        CountDownLatch同步工具:
                在逻辑线程外多起一个线程用于控制该同步工具的计数器;
                当计数器数值为0的时候,使用了该工具的多个线程,同时继续运行;(计数器1倒计时起跑,计数器2等待结果,最后公布成绩)
                计数器1,1个人通知多个人,计数器2,多个人通知1个人;
        Exchange同步工具:
                两个线程执行完成事务后,早完成的人等待第二个人完成后,二着交易数据;
        阻塞队列:
                就是了解添加和移除的3套API
                运用:用两个长度为1的队列实现互相通知间隔运行这样的同步效果;
        同步集合类:
                HashMap死循环原理,循环的时候,集合remove()了一次,使得hasNext()无限为真(courosr超过了集合长度后无限++,判断都为真);
                CopyOnWriteArrayList():迭代过程中删除元素出现coursr长度出现问题造成错误,可以同个这个类屏蔽这个问题;
                实际上,remove()后使用previous(),也一样可以解除这个问题;(http://bbs.itheima.com/thread-149741-1-1.html)
----------------------------------------------------->
反射(高新1)
        HelloWorld:
                java中的类是用来描述普通事物的(内部有什么特征,什么功能等等),而反射中很重要的类Class,是用来描述<java中的类>这类事物的;
                Class描述了某个java类内部有什么属性什么方法,各种参数,等等;反射就是基于Class这个类展开的;也就是反射的源;
        获取字节码:
                1.类名.class;2.对象.getClass();3.Class.forname(记住加包名String classname);
        字节码类型:       
                基本数据类型对象:
                        8个基本类型和void类型:int.class,long.class,void.class等等;判断(isPrimitive();)
                        封装类中的属性:Integer.TYPE == int.class;
                数组类型:
                        int[].class;判断isArray();
        注意点:
                不写权限修饰,其实是protected,也是要使用暴力反射的;
                反射数组为参数的方法时(比如某个类的main函数),invoke(这里数组要转成Object,否则会被1.5的可变参数原理拆开)
        权限:        clazz.newInstance()只要能访问就能反射 而普通getXxx()反射只能反射public修饰的内容
        数组:
                类型判断,数组之间,只要元素类型一样,维度一样,就表示两个类型一样;(编译都不通过)
                Array.get(arr, index)(这里没用到它的字节码,判断是否是数组的时候可以用字节码)

        API:        不记录了,就那几个;暴力反射记住getDeclared和setAccessible这两个单词;
        补充:        泛型在编译成.class文件后就消失了,现在需求需要获取泛型的参数列表;
                通过反射该泛型的方法,然后反射方法中的参数类型;getGenericParameterTypes();参数类ParameteriezdType,用其中方法获取参数类型;
<---------------------------------------
回复 使用道具 举报

不要奇怪,我也是奋战在第一线的:lol。。。飞哥不是面试了47期的吗?
回复 使用道具 举报
本帖最后由 郑飞 于 2014-10-26 07:58 编辑
戏言丶 发表于 2014-10-21 03:28
不要奇怪,我也是奋战在第一线的。。。飞哥不是面试了47期的吗?

没啊 有事 时间紧 而且不自信 就没参加 反正啥时候整明白了再面试 可能快了
------------------------------------------->
IO流
        实际上就是通过java语言调用系统资源(各种平台的本地方法)从各种数据处理设备中获取和写入数据的工具;
        最常用的就是缓冲流,在流内部定义缓冲数组,实现数据批量读取和写入,从而提高数据转移的效率;
        缓冲流 就是利用java语言调用本地方法 将数据读取到流内部的数组中 当数组装满后自动存入目的地
        至此,字节缓冲流已经可以应付基本的数据处理;但是java为了提高开发的效率,就提供了各种高级的有针对性的功能流;
        以下就各种高级流做阐述:
        1.BufferedReader,BufferedWriter/字符缓冲流
                最显著的功能提升就是,行读取:readLine();这个流的write()方法可以自动判断缓冲流中数据是否装满,装满了会自动刷新到目的地,所以不用每次都刷新;
        2.LineNumberReader,基于BufferedReader增加了行符这个属性,可以获取,自定义,修改行符;
        学到这里,插入File概念:这是一个文件系统的封装类,将文件,文件夹封装成一个对象,扩展了流的操作范围(流只能操作数据,File的引入,使流可以间接的操作文件系统);
        File类中有各种功能API对File对象进行各种操作,常用的有,新建,删除,获取文件名,获取上级File,获取子级File列表,判断是文件还是文件夹;(复制多级文件夹中用到这些)
        合并流只有读取流,其功能是将多个读取流拼成一个读取流:也就是将多个地方的数据(每个数据都关联一个普通读取流),统一输出到一个目的地(合并目的地);
        反过来切割就简单了,把源输入到一个输入流,这个输入流对应多个输出流,输出到不同的目的地;(用最基本的流就能实现,没新知识);
        
        以上就是IO流中最常用,最基本的东西;下面列举一些有针对性的流:
        1.ObjectInputStream:操作对象的流;将对象数据化,存入到硬盘上;要点:使用前要将对象序列化,即对象所在类实现Serializable接口;
        补充:
                为了方便序列化,自定义常量public static final long serialVersionUID = 35l;效果:当类改变后,一样可以识别该类,使得原有的对象可以使用在改变后的类中;
                静态成员不能序列化;transient修饰成员,可以强行不对该成员序列化;
        2.PipedInputStream(PipedInputStream pis)管道流:普通流输入--数组--输出,而管道流:输入--输出;(必须使用多线程,处理同步问题)        
                管道流需要使用多线程的原因:于其他流比较,管道流从代码变现形式上少了中间中转(其实内部还是有中转的),那我们就无法使用循环控制到二者的运行顺序,造成了同步安全问题;
                由于结构上和以往流的区别,所以要结合视频中的例子,看API此2个类的类说明,记住数据流向;Input读取(),Output写入;
        RandomAccessFile:
                        随机访问文件;直接继承Object;内部封装了字节输入输出流;
                        使用的时候可以指定读取模式r只读和rw读取,r的时候,如果文件不存在怎报错,rw的时候如果文件不存在,怎创建;
                        内部相当于数组,没write()一次,相当于存入一个数组元素,所以该读取的时候通过变动指针实现针对性读取(随机读取,想读哪就读哪);所以存的时候数据长度最好

要有规律,这样才好控制指针;
                        读:seek(8)直接定位(象棋车)从第9个位置开始取;skipBytes(),只能往下跳不能往回走(象棋卒);
                        写:指针控制和读一样,写入动作其实是修改功能,直接覆盖当前位置数据;
                        由于write()只读8位造成数据丢失的特点,该类提供了对基本数据类型的写入和读取,writeInt(),readInt();
                用处:对数据的分段写入和读取;例子存取个人信息(姓名按16字节8个字长度存,名字4个字节32位(int)长度存),长度统一后,进行遍历或者单取,都很方便;
        DataInputStream:                 操作基本数据类型就用这个流;
        ByteArrayInputStream:
                用流的存取思想来操作数组元素;
                接收一个byte数组为数据源;ByteArrayOutputStream数据目的地为其内部封装的缓冲数组,会自动增长长度;(可以理解为其对象就是一个数组,可使用数组方法),还有个特殊方法writerTo()把数据放到另外一个流中,例如FileInputStream();
               同类流:CharArrayReader,CharArrayWriter;StringReader,StringWriter;
        编码问题:
                能指定编码的流InputStreamReader,OutputStreamWriter;PrintStream,PrintWriter(只能打印)
                编码 String--byte[] :str.getBytes(charsetName);解码: byte[]--String:new String(byte[],charsetName);
                解决乱码:编一次解一次;        
<--------------------------------------------------



回复 使用道具 举报
郑飞 发表于 2014-10-21 03:29
没啊 有事 时间紧 而且不自信 就没参加 反正啥时候整明白了再面试 可能快了 ...

没事,这种事急不来,我也准备了蛮长时间的。飞哥可要注意身体,都这么晚,虽然我也挺晚的
回复 使用道具 举报
郑飞 高级黑马 2014-10-21 03:50:05
7#
戏言丶 发表于 2014-10-21 03:42
没事,这种事急不来,我也准备了蛮长时间的。飞哥可要注意身体,都这么晚,虽然我也挺晚的 ...

嗯 我是老毛病了 你们还没成习惯的千万别太晚 很难改的 差不多了 就睡了
回复 使用道具 举报
郑飞 发表于 2014-10-21 03:50
嗯 我是老毛病了 你们还没成习惯的千万别太晚 很难改的 差不多了 就睡了

我也有一段时间了。。。这个点差不多了,睡了
回复 使用道具 举报
感谢分享
回复 使用道具 举报
表示你写的这些术语感觉好深奥啊  有木有
回复 使用道具 举报
郑飞 高级黑马 2014-10-21 08:47:47
11#
我为你着迷 发表于 2014-10-21 08:33
表示你写的这些术语感觉好深奥啊  有木有

有些和视频里差不多 只是用了自己的语言总结的 这样我个人容易记 还有些觉得看了视频还不理解平时有百度看过 还有的就是有意简化成简练的语言 所以有些部分比如多线程会多一点自己的词语 集合的感觉API多一点 应该还好 供大家参考 结合你们自己的总结就好了
回复 使用道具 举报
谢谢分享~
回复 使用道具 举报
睡的比...晚 起的比鸡晚........ 好奋斗的骚年
回复 使用道具 举报
楼主晚睡且早起?
回复 使用道具 举报
郑飞 来自手机 高级黑马 2014-10-21 09:28:26
15#
前些天有事拉下不少,这两天恶补下,不过休息了几天回过头来能真正知道自己到底掌握多少还缺那里,发扬下阿Q精神。
回复 使用道具 举报
飞哥精神值得我们学习,总结的内容很好!
回复 使用道具 举报
总结很不错。。。:handshake
回复 使用道具 举报
嗯,好东西。。。
回复 使用道具 举报
楼主是流弊达人,鉴定完毕,向你学习
回复 使用道具 举报
郑飞 高级黑马 2014-10-22 01:13:48
20#
贾浩田 发表于 2014-10-22 00:25
楼主是流弊达人,鉴定完毕,向你学习

不是的 因为面试要求知识系统性比较强 而自己动脑做总结 能深刻的系统的复习所有知识 我觉这是个"捷径"
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马