Java第三周学习日记

Day01

1.线程

进程:进程就是正在运行的应用程序。进程负责了内存空间的划分。

线程:一个进程中的代码是由线程去执行的,线程也就是其中一个执行路径。

多线程:一个进程中有多个线程可以同时执行任务。

线程的状态

 

创建:新创建了一个线程对象。

可运行:线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取cpu的执行权。

运行:就绪状态的线程获取了CPU执行权,执行程序代码。

阻临时塞: 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

死亡:线程执行完它的任务时。

多线程的好处:

1.解决了一个进程中可以同时执行多个任务的问题。

2.提高了资源利用率。

多线程的弊端:

1.对线程进行管理要求额外的 CPU开销。线程的使用会给系统带来上下文切换的额外负担。

2.降低了一个进程中线程的执行概率

3.出现线程安全问题

4.引发死锁现象

自定义线程的实现方式:

  方式一

    1.自定义一个类继承Thread类

    2.重写Thread类的run方法,把自定义线程的任务代码写在run方法上。

    3.创建Thread的子类对象,并且调用start方法启动一个线程。

    注意:千万不要直接调用run方法,调用start方法的时候,线程就会开启,线程一旦开启就会执行run方法中的代码。如果直接调用run方法,那么就相当于调用了一个普通的方法而已。

  方式二

    1.自定义一个类实现Runnable接口

    2.实现Runnable接口的run方法,把自定义线程的任务定义在run方法上

    3.创建Runnable实现类的对象

    4.创建Thread类对象,并把Runnable实现类的对象作为实参传递

    5.调用Thread对象的start方法。

    问题一:请问Runnable实现类的对象是线程对象吗?

    Runnable实现类的对象并不是一个线程对象,只不过是实现了Runnable接口的对象而已。

    只有Thread或是Thread的子类才是线程对象。

    问题二:为什么要把Runnable实现类的对象作为实参传递给Thread对象呢?作用是什么?

    作用就是把Runnable实现类的对象的run方法作为了线程的任务代码去执行了。

线程安全问题

  线程安全问题出现的根本原因:

    1.存在两个或者两个以上的线程对象共享同一个资源。

    2.多线程操作共享资源的代码有多句。

  线程安全问题的解决方案:

    方式一:可以使用同步代码块

      格式:synchronized(锁对象){}

    同步代码块要注意的事项:

      1.锁对象可以使任意的一个对象

      2.一个线程在同步代码块中sleep了,并不会释放锁对象。

      3.如果不存在着线程安全问题,千万不要使用同步代码块,因为会降低效率。

      4.锁对象必须是多线程共享的一个资源,否则锁不住。

    方式二:同步函数:同步函数就是使用synchronized修饰一个函数

    同步函数要注意的事项:

      1.如果是一个非静态的同步函数的锁对象是this对象,如果是静态的同步函数对象的锁对象是当前函数所属的类的字节码文件(classwe对象)

      2.同步函数的锁对象是固定的,不能由个人来指定。

      3.如果将同步函数设为非静态,会生成多个锁对象,锁不住,只能设置成静态的同步函数,但是这样一来只能由一个线程执行完所有代码了(见老两口取钱例子)

    推荐使用:同步代码块

    原因:   

      1.同步代码块的锁对象可以由我们随意指定,方便控制。同步函数的锁对象是固定的,不能由我们来指定。

      2.同步代码块可以很方便控制需要被同步代码的范围,同步函数必须是整个函数的所有代码都被同步

死锁现象

  出现的原因:

    1.存在两个或者两个以上的线程

    2.存在两个或两个以上的共享资源。

  死锁现象无法解决。

线程的通讯

  一个线程完成了自己的任务时,要通知另外一个线程去完成另外一个任务。

  wait():一个线程如果执行了wait方法,那么该线程就会进去一个以锁对象为标识符的线程池中等待。

  notify():如果一个线程执行notify方法,那么就会唤醒以锁对象为标识符的线程中等待线程中其中一个。

  wait与notify方法要注意的事项:

    1.wait方法与notify方法是属于Object对象的

    2.wait方法与notify方法必须要在同步代码块或者是同步函数中才能使用

    3.wait方法与notify方法需要由锁对象调用

停止线程

  1.一般是通过一个变量去控制的。

  2.如果需要停止一个等待状态下的线程,我们需要通过变量配合notify或者interrupt方法来使用。

后台线程与join方法

  任何线程默认都不是守护线程,通过setDaemon(true)来设置成守护线程。应用场景:当需要某一线程随主线程的存在而存在,随主线程消失而消失时使用。

  join方法:一个线程如果执行了join语句,那么就有新的线程加入,执行该语句的线程必须要让步给新加入的线程先完成任务,然后才能继续执行。

Day02

1.集合

集合是存储对象数据的容器。

集合做什么

1:将对象添加到集合

2:从集合中删除对象

3: 从集合中查找一个对象

4:从集合中修改一个对象就是增删改查

集合比数组的优势:

  1.集合可以存储任意类型的对象数据,数组只能存储同一种数据类型的数据。

  2.集合的长度是会发生变化的,数组的长度是固定的。

——————————| Collection 单例集合的跟接口

————————————| List 如果是实现了List接口的集合类,具备的特点是:有序,可重复

————————————| Set 如果是实现了Set接口的集合类,具备的特点:无序,不可重复

---|Collection: 单列集合

           ---|List: 有存储顺序, 可重复

              ---|ArrayList:    数组实现, 查找快, 增删慢

                                     由于是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快

              ---|LinkedList:  链表实现, 增删快, 查找慢

                                     由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素. 这样的增删效率较高但查             询时需要一个一个的遍历, 所以效率较低

              ---|Vector:    底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的。但是V完成投入是线程安全的。操作效率低

              和ArrayList原理相同, 但线程安全, 效率略低

                                   和ArrayList实现方式相同, 但考虑了线程安全问题, 所以效率略低

            笔试题:说出ArrayList与Vector的区别?

                相同点:底层都是使用了Object数组实现的。

                不同点:

                   1.ArrayList是线程不同步的,操作效率高。Vector是同步的,操作效率低。

                   2.ArrayList是JDK1.2出现的,Vector是JDK1.0时出现的。

          ---|Set: 无存储顺序(即存储元素的顺序与输出顺序是不一致的),元素不可重复。

              ---|HashSet  底层是使用了哈希表来支持的。特点:存取速度快

              ---|TreeSet  如果元素具备自然顺序的特性,那么就按照元素的自然顺序进行排序存储。

              ---|LinkedHashSet(少)

---| Map: 键值对

       ---|HashMap

       ---|TreeMap

       ---|HashTable

       ---|LinkedHashMap

集合类(Collection)的共性方法

增加:

       1:add()   将指定对象存储到容器中

                      add 方法的参数类型是Object 便于接收任意对象

       2:addAll() 将指定集合中的元素添加到调用该方法和集合中

删除:

       3:remove() 将指定的对象从集合中删除

       4:removeAll() 将指定集合中的元素删除,删除交集

       5:clear() 清空集合中的所有元素

   6:retainAll() 保留交集,删除交集以外的对象

获取:  

   7:int size()    返回集合容器的大小

判断

       6:isEmpty() 判断集合是否为空

       7:contains() 判断集合何中是否包含指定对象 

       8:containsAll() 判断集合中是否包含指定集合

                            使用equals()判断两个对象是否相等

迭代: toArray()   集合转换数组

   iterator()

Day03

1.迭代器

迭代器的作用:用于抓取集合中的元素。

迭代器的使用:

Iterator it = c.iterator();//返回一个迭代器。疑问:iterator()方法返回的是一个借口类型,为什么接口又可以调用方法使用呢?iterator实际上返回的是iterator接口的实现类对象。

迭代器的方法:

  hashNext()//问是否有下一个元素,如果有元素可以遍历,返回true,否则返回false

  E next()    //获取元素,返回迭代的下一个元素

    NosuchElementException异常:没有可以迭代的元素了

  void  remove()//从迭代器指向的collection中移除迭代器返回的最后一个元素。(需要配合next方法使用)

迭代器的工作原理:

  获取迭代器时,迭代器中有一个指针指向了集合中的第一个元素。

  hashnext():当前指针是否有指向元素,如果有返回true,否则返回false

  next():获取当前指针指向的元素并返回当前的元素,然后指针向下移动一个单位。

 2.list接口特有的方法

如果是实现了List接口的集合类,该集合类具备的特点:有序,可重复。

有序:集合的有序不是指自然顺序,而是指添加进去的顺序与元素出来的顺序是一致的。

  List list = new ArrayList();

List方法中特有的方法:

1:增加

        void add(int index, E element) 指定位置添加元素           

        boolean addAll(int index, Collection c) 指定位置添加集合 

2:删除

  E remove(int index) 删除指定位置元素

3:修改

       E set(int index, E element)    返回的是需要替换的集合中的元素

4:查找:

       E get(int index)             根据索引值返回元素注意: IndexOutOfBoundsException

       int indexOf(Object o)        找出指定元素在集合中的索引值 // 找不到返回-1

       lastIndexOf(Object o)  找出指定元素最后一次出现的索引值

5:求子集合

        List<E> subList(int fromIndex, int toIndex) // 不包含toIndex 凡是有开始和结束索引值,Java中都是包头不包尾。

6.迭代:listIterator()返回的是一个List接口中特有的迭代器

listIterator除了继承Iterator的方法之外,还拥有自己特有的方法:  

add(E e)    把当前元素插入当前指针指向的位置上,将指定的元素插入列表(可选操作)。该元素直接插入到 next 返回的下一个元素的前面(如果有)

void set(E o)   替迭代器返回的最后一个元素。用指定元素替换 nextprevious 返回的最后一个元素

hasPrevious()    判断是否存在上一个元素。逆向遍历列表,列表迭代器有多个元素,则返回 true

previous()       当前指针先向上一个单位,然后再取出当前指针指向的元素,返回列表中的前一个元素。

next()      先取出当前指针指向的元素,然后指针指向下一个移动一个单位。

ctrl + shift + / 多行注释

ctrl + shift + \ 取消多行注释

List接口中特有的方法具备的特点:操作的方法都存在索引值。所以以后想要使用索引值,必须用LIST,因为只有LIST接口下面的集合类才具有索引值,其他接口下面的集合类都没有索引值。

迭代器在遍历元素的时候要注意的事项:

  在迭代器迭代元素的过程中,不允许使用集合对象改变集合中的元素个数,如果需要增加或者删除,只能使用迭代器的方法进行操作。、

  如果使用过了集合对象改变集合中的元素个数,那么就会出现C通俗人人通M偶滴覅擦头你Exception

  迭代元素的过程中:迭代器一旦创建到使用结束的时段

 

2.List接口下面的实现类

常用:ArrayList  LinkedList  Vector(了解)

2-1 ArrayList(主要学习实现原理和特点)

  ArrayList底层是维护了一个Object数组实现的,特点:查询速度快,增删满。

  ArrayList特有的方法

    ensureCapacity( int minCapacity)

    trimToSize()

笔试题目:使用ArrayList无参的构造函数创建一个对象时,默认的容量是多少?如果长度不够使用时又自动增长多少?

  ArrayList底层维护了一个Object数组实现的,使用无参构造函数时,Object数组默认的容量是10,当长度不够时,自动增长0.5倍

  什么时候使用ArrayList:如果目前的数据是查询比较多,增删比较少的时候,那么就使用ArrayList存储这批数据。

2-2 LinkedList

  LinkedList底层是使用了链表数据结构实现的。特点:查询速度慢,增删快。

  LinkedList特有的方法

1:方法介绍

addFirst(E e)

addLast(E e)

getFirst()

getLast()

removeFirst()

removeLast()

如果集合中没有元素,获取或者删除元素抛:NoSuchElementException

2:数据结构

              1:栈 (1.6):主要是用于实现堆栈数据结构的存储方式

                  先进后出

                  push()

                  pop()

              2:队列(双端队列1.5):主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式。

                  先进先出

                  offer()

                  poll()

    3:返回逆序的迭代器对象     

      descendingIterator()   返回逆序的迭代器对象

机试题目:使用LinkedList实现堆栈数据结构的存储方式与队列数据结构存储方式。

堆栈数据结构存储特点:先进后出,后进先出。

队列数据机构的存储特点:先进先出,后进后出。

Day04

 Set分支

1.HashSet

  HashSet底层是使用了哈希表来支持的,特点:存取速度快。因为是通过哈希表来直接找到对应元素。

HashSet的实现原理:

  往HashSet添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值,然后通过元素的哈希值经过移位等运算,就可以算出元素在哈希表中的位置。

  情况一:如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置上。

  情况二:如果算出该元素的存储位置目前已经存在其他元素了,那么会先调用该元素的equals方法与该位置的元素再比较一次,如果equals返回的是true,那么该元素与这个位置上的元素就视为重复元素,不允许添加,如果equals方法返回的是false,那么该元素允许添加。

    hashCode要注意的是,不一定都是返回内存地址作为哈希值,因为可能被其他类给重写,比如String类就是得到一个经过公式计算出的数值。

2.TreeSet

  如果元素具备自然顺序(大小顺序)的特性,那么就按照元素自然顺序的特性进行排序存储。

 Treeset添加自定义元素

Treeset要注意的事项:

  1.往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。

  2.往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性(例如想要添加自定义对象),那么该元素所属的类必须要实现Comparable接口,把元素的比较规则定义在ComparableTo(to)方法上。该方法会返回一个整型变量,负整数,零或正整数,根据此对象是小于、等于还是大于对象。

  3.如果比较元素的时候,compareTo方法返回的是0,那么该元素就被视为重复元素,不允许添加。(注意:TreeSet与hashCode或者是equals方法是无关的,依赖的是compareTo方法)

  4.往TreeSet添加元素的时候,如果元素本身没有具备自然顺序的特性,而元素所属的类也没有实现comparable接口,那么必须要在创建TreeSet的时候传入一个比较器。

如何自定义比较器:自定义一个类实现comparator接口,把元素与元素之间的比较规则定义在compare方法即可

  自定义比较器的格式

    class 类名 implements Comparator    {

     }

  步骤:1.创建一个比较器对象

     2.新建TreeSet时传入比较器对象

推荐使用:使用比较器Comparator

  5.往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口,在创建TreeSet对象的时候也传入了比较器,那么以比较器优先

Treeset的实现原理

注意:如果三个元素无法形成树杈,那么会进行自动调整,调整成一个树杈。

Day05

1.泛型

泛型是JDK1.5使用的新特性。

泛型的几种形式

ArrayList<String> list = new ArrayList<String>();//表示该容器只能存储字符串类型的数据。

以下两种写法主要是为了兼顾新老系统的兼用性问题。

  ArrayList<String> list = new ArrayList();

    ArrayList list = new ArrayList<String>();

 泛型的好处:

  1.将运行时的异常提前至了编译时。(例如list.add(123)在不加入泛型时只有运行才会报错,但是加上泛型后,则在编译时就会报错)

  2.避免了无谓的强制类型转换

泛型在集合中的常见应用:

注意:泛型没有多态的概念,左右两边的数据类型必须要一致,或者只写一边的泛型类型(因为编译只看左边)

推荐使用:两遍都写泛型。

 

需求:定义一个方法可以接收任意类型的参数,而且返回值类型必须要与实参的类型一致

引出的新知识点:自定义泛型:一个数据类型的占位符或者是一个数据类型的变量。

1.方法上自定义泛型:

方法泛型注意的事项:

  1.在方法上自定义泛型,这个自定义泛型的具体数据类型是在调用该方法的时候,传入实参时确定具体的数据类型的。

  2.自定义泛型只要符合标识符的命名规则即可,但是自定义泛型一般我们都习惯使用一个大写字母表示。常见:T :Type  E :Element

格式:

  修饰符 <声明自定义的泛型>返回值类型 函数名(使用自定义泛型){

  }

  public static <T>T  getDate(T o){

    return o;

  }

在泛型中不能使用基本数据类型,如果需要使用基本数据类型,那么就使用基本数据类型对应的包装类型。

byte------Byte

short-----Short

int--------Integer

long------Long

double---Double

float------Float

boolean--Boolean

char------Character

小例子:元素翻转

 

 

2.泛型类:

泛型类的定义格式:

class 类名<声明自定义泛型>{

}

优点:不必在每个方法上生命自定义泛型

工具类方法一般写成静态的。

泛型类要注意的事项:

  1.在类上自定义泛型的具体数据类型是在使用该类的时候创建对象的时候确定的

  2.如果一个类在类上已经声明了自定义泛型,如果使用该类创建对象的时候没有指定泛型的具体数据类型,那么默认为Object类型。

  3.在类上自定义泛型不能作用于静态的方法,如果静态的方法需要使用自定义泛型,那么需要在方法上自己声明使用。

 

3.泛型接口:

泛型接口的定义格式:

  interface 接口名<声明自定义泛型>{

}

泛型接口要注意的事项:

  1.接口上自定义的泛型的具体数据类型是在实现一个接口的时候指定的,

  2.在接口上自定义的泛型如果在实现接口的时候没有指定具体的数据类型,那么默认为Object类型。

需求:目前我实现一个接口的时候,我还不明确我目前要操作的数据类型,我要等到创建这个接口实现类对象的时候才能指定泛型的具体数据类型。

如果要延迟接口自定义泛型的具体数据类型,那么格式如下:

格式:

  public class Demo4<T> implements dao <T>

泛型的上下限:

需求1:定义一个函数可以接收任意类型的集合对象,要求接收的集合对象只能存储Interger或者是Integer的父类类型数据。

需求2:定义一个函数可以接收任意类型的集合对象,要求接收的集合对象只能存储Number或者是Number的子类类型数据。

泛型中的通配符:?

 ? super Integer :  只能存储Integer或者是Integer父类元素,泛型的下限

 ? entendd Number:只能存储Number或者是Number类型的子类数据,泛型的上限

 

posted @ 2016-09-02 15:17  stubbornnnnnnn  阅读(175)  评论(0编辑  收藏  举报