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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小石姐姐 于 2018-8-3 10:01 编辑

day3 - day6 学习总结

List集合:
经常用到的是ArrayList和LinkedList;它们都是Collection接口的子类.
底层的数据结构:链表
特点:查询慢,增删快,线程不安全,效率高
遍历集合的方式:1.Iterator迭代器 ,2.增强for
应用场景:存储的数据查询少, 增删多的场景
使用格式:
定义ArrayList集合对象:
[AppleScript] 纯文本查看 复制代码
Collection<String>  coll=new ArrayList<String>;左父右子,可以在调用子类时可以使用父类的方法
方法如下:

[AppleScript] 纯文本查看 复制代码
coll.add(元素)  把给定的对象添加到当前集合中 。
coll.clear() :清空集合中所有的元素。
coll.remove(元素) : 把给定的对象在当前集合中删除。
coll.add(索引值,?元素) : 将指定的元素,添加到该集合中的指定位置上。
coll.get(索引值) :返回集合中指定位置的元素。
coll.remove(索引值) : 移除列表中指定位置的元素, 返回的是被移除的元素。
coll.set(索引值,元素) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
collections.sort(coll):用来排序集合;
boolean b=coll?contains(元素) : 判断当前集合中是否包含给定的对象。
boolean?b=coll.isEmpty() : 判断当前集合是否为空。
int?i=coll.size() : 返回集合中元素的个数。
Object[]?o=coll.toArray() : 把集合中的元素,存储到数组中。集合转化成数组*/
LinkedList集合的使用方法和Collection父类差不多,但又有区别.
LinkedList<String> linked=new LinkedList<>();
        linked.addFirst(元素) :将指定元素插入此列表的开头。
        linked.addLast(元素) :将指定元素添加到此列表的结尾。
        linked.?push(元素) :将元素推入此列表所表示的堆栈。addFirst和相当
        linked.getFirst() :返回此列表的第一个元素。
        linked.getLast() :返回此列表的最后一个元素。
        linked.removeFirst() :移除并返回此列表的第一个元素。
        linked.removeLast() :移除并返回此列表的最后一个元素。
        linked.pop() :从此列表所表示的堆栈处弹出一个元素。
        boolean bo=linked.isEmpty() :如果列表不包含元素,则返回true。
     
Set集合:
包括HashSet LinkedHashList,
集合体系特点:1.元素不重复,2.没有索引,        
HashSet特点:1.        元素不可重复  主要用于去重
                      2.没有索引,
                         3.元素存放无序(存取顺序有可能不一致
                         4.底层采用 哈希表结构 .(查询快)
                            (哈希表=数组+链表)
                            (哈希表=数组+红黑树)(提高查询的速度)
遍历集合的方式:增强for                             
使用格式和List集合一样;  
多线程
并发与并行
并行:指两个或多个事件在同一时刻发生(同时发生)。
并发:指两个或多个事件在同一个时间段内发生。

线程与进程
进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间
线程:进程内部的一个独立执行单元;一个进程可以同时并发的运行多个线程
进程与线程的区别
进程:有独立的内存空间,进程中的数据存放空间(堆空间和栈空间)是独立的,至少有一个线程。
线程:堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小的多。
注意:
Java 程序的进程里面至少包含两个线程,主进程也就是 main()方法线程,另外一个是垃圾回收机制线程。在 Java 运行时至少会启动两个线程。
创建线程类
Thread  : 线程!
Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的
Java中通过继承Thread类来创建并启动多线程的步骤如下:
1. 定义Thread类的子类,并重写该类的run()方法,把run()方法称为线程执行体。
2. 创建Thread子类的实例,即创建了线程对象
3. 调用线程对象的start()方法来启动该线程
代码如下:
测试类:

[AppleScript] 纯文本查看 复制代码
public class Demo01 {
public static void main(String[] args) {   
//创建自定义线程对象        
MyThread mt = new MyThread("新的线程!");        
//开启新线程        
mt.start();        
//在主方法中执行for循环        
for (int i = 0; i < 10; i++) {        
System.out.println("main线程!"+i);            
}        
}   
}
[align=left]
自定义线程类:

[Java] 纯文本查看 复制代码
public class MyThread extends Thread {
//定义指定线程名称的构造方法   
public MyThread(String name) {   
//调用父类的String参数的构造方法,指定线程的名称        
super(name);        
}   
/**   
* 重写run方法,完成该线程执行的逻辑   
*/   
@Override   
public void run() {   
for (int i = 0; i < 10; i++) {        
System.out.println(getName()+":正在执行!"+i);            
}        
}   
}
多线程原理
  
     mt.start();
依靠CPU的随机切换来运行
每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。
多线程每个线程都有自己单独的栈内存!
Thread类
  java.lang.Thread 类
每一个Thread类的对象就是一个线程
构造方法:
[Java] 纯文本查看 复制代码
1. public Thread() :分配一个新的线程对象。
2. public Thread(String name) :分配一个指定名字的新的线程对象。(给不同的线程设置不同的名字)
3. public Thread(Runnable target) :分配一个带有指定目标新的线程对象。(Runnable )
4. public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。

常用方法:
[Java] 纯文本查看 复制代码
1. public String getName() :获取当前线程名称。
public String setName() :设置当前线程名称.
1. public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。
2. public void run() :此线程要执行的任务在此处定义代码。
3. public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂(暂时停止执行)。
4. public static Thread currentThread() :返回对当前正在执行的线程对象的引用。
5. Pulibic void setPriority 设置线程执行的优先级 ,从0 - 10 级别越高,运行到的几率就越高!
创建线程方式二
采用 java.lang.Runnable 也是非常常见的一种,我们只需要重写run方法即可。(相对用的比较多)
代码如下:
1. 定义类, 实现Runnable接口
2. 重写 run() 方法
3. 创建Runnable实现类对象
4. 创建Thread类对象, 在构造方法中传入Runnable实现类对象
5. 通过Thread对象调用start()方法启动线程
[Java] 纯文本查看 复制代码
public class MyRunnable implements Runnable  {       //      1.    创建Runnable接口实现类[/size][/font][/align][/align][align=center][font=微软雅黑][size=3] [/size][/font][/align][align=center][align=left][font=微软雅黑][size=3]@Override   // 2. 在实现类中重写R接口的run方法 设置线程任务     [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]public void run() {    [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]for (int i = 0; i < 20; i++) {        [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]System.out.println(Thread.currentThread().getName()+" "+i);            [/size][/font][/align][/align][align=center]
[/align][align=center][align=left][font=微软雅黑][size=3]}[/size][/font][/align][/align][align=center][font=微软雅黑][size=3] [/size][/font][/align][align=center][align=left][font=微软雅黑][size=3]public class Demo {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]    public static void main(String[] args) {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        // 3. 创建自定义类对象  线程任务对象[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        MyRunnable mr = new MyRunnable();[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        //  4.    创建线程对象[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        Thread t = new Thread(mr, "小强");[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        t.start();// 5. 调用Thread类中的start[/size][/font][/align][/align][align=center][font=微软雅黑][size=3] [/size][/font][/align][align=center][align=left][font=微软雅黑][size=3]        for (int i = 0; i < 20; i++) {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            System.out.println("旺财 " + i);[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        }[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]    }[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]}
1. 避免了单继承的局限性!
2. 增强了程序的扩展性,降低了程序的耦合性(解耦)
匿名内部类方式实现线程的创建
简化代码作用
使用线程的内匿名内部类方式,可以方便的实现每个线程执行不同的线程任务操作。使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法:
[Java] 纯文本查看 复制代码
public class NoNameInnerClassThread {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]   public static void main(String[] args) {            [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]// new Runnable(){      [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]// public void run(){          [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]// for (int i = 0; i < 20; i++) {              [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]// System.out.println("张宇:"+i);                  [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]// }              [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]// }            [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]//    }; //‐‐‐这个整体  相当于new MyRunnable()    [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        Runnable r = new Runnable(){[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            public void run(){[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]                for (int i = 0; i < 20; i++) {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]                   System.out.println("张宇:"+i);  [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]                }[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            } [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        };[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        new Thread(r).start();[/size][/font][/align][/align][align=center][font=微软雅黑][size=3] [/size][/font][/align][align=center][align=left][font=微软雅黑][size=3]       for (int i = 0; i < 20; i++) {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]           System.out.println("费玉清:"+i);  [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        }[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]   } [/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]}
     异常和异常的处理
异常:指的是程序在执行过程中,出现的非正常的情况,最终导致JVM的非正常停止
注意:
在Java中,每种异常都有对应的类来描述,发生了一个异常,就是出现了这个类的对象,异常并不是语法错误
Java.lang.Throwable  //体系最顶层
Error           //不应该试图捕获的严重问题,不能处理的错误
Exception       //可以处理的异常
Exception:编译器异常,进行编译(写代码)java程序出现的问题
RuntimeException:运行期异常,java程序运行过程中出现的问题
Error:不能处理的错误,必须修改源码
异常的产生过程解析:
当执行的代码发生异常操作时,JVM会创建一个对应的异常类对象,包含异常的内容,原因,位置
如果执行代码没有对异常进行try...catch处理,则会向该方法调用处抛出,如果所有方法包括main方法都没有处理,会被JVM按照默认方式进行处理
将异常信息(内容,原因,位置)打印到控制台
终止当前的程序
throw关键字
作用:
可以使用throw关键字在指定的方法中抛出指定的异常
使用格式:
throw new xxException("异常产生的原因");
注意:
throw关键字必须写在方法的内部
throw关键字后边new的对象必须是Exception或者Exception的子类对象
throw关键字抛出指定的异常对象,必须处理这个异常对象
如果创建的是RuntimeException或者是RuntimeException的子类时,可以交给JVM默认处理
如果该异常是编译期异常
throws关键字:异常处理的第一种方式,交给别人处理
作用:
当方法内部抛出异常对象的时候,那么就必须处理这个异常对象
可以使用throws关键字处理异常对象,会把异常对象生命抛出给方法的调用者处理,最终交给JVM处理,中断运行
使用格式:
在方法声明时使用


throws关键字必须写在方法声明处
throws关键字后边声明的异常必须是Exception及其子类
方法内部如果抛出了多个异常对象,那么throws也必须声明多个异常
如果抛出的多个异常对象有父子类关系,那么直接声明父类异常即可
调用了一个声明抛出异常的方法,必须处理声明的异常
要么继续使用throws声明抛出,交给方法的调用者
要么try...catch自己处理
[Java] 纯文本查看 复制代码
[/size][/font][/align][/align][align=left][align=center][align=left][font=微软雅黑][size=3]    [mw_shl_code=java,true]  public static void main(String[] args) throws FileNotFoundException, IOException {[/size][/font][/align][/align][font=微软雅黑][size=3]

[align=center][align=left]    public static void main(String[] args) throws IOException {[/align][/align]
[align=center][align=left]        readFile("C:\\a.exe");[/align][/align]
[align=center][align=left]    }[/align][/align]
[align=center][align=left]       private static void readFile(String fileName) throws FileNotFoundException, IOException {[/align][/align]

[align=center][align=left]    private static void readFile(String fileName) throws IOException {[/align][/align]
[align=center][align=left]        if (!fileName.equals("C:\\a.text")) {[/align][/align]
[align=center][align=left]            throw new FileNotFoundException("传递的文件路径不存在");[/align][/align]
[align=center][align=left]        }[/align][/align]
[align=center][align=left]        /*[/align][/align]

[align=center][align=left]            如果传递的路径,不是.txt结尾[/align][/align]

[align=center][align=left]            抛出IO异常对象,告知方法的调用者文件的后缀名不正确[/align][/align]

[align=center][align=left]         */[/align][/align]
[align=center][align=left]        if (fileName.endsWith(".txt")) {[/align][/align]
[align=center][align=left]            throw new IOException("文件的后缀名不正确");[/align][/align]
[align=center][align=left]        }[/align][/align]
[align=center][align=left]        System.out.println("路径没有问题,读取文件");[/align][/align]
[align=center][align=left]    }[/align][/align]
[align=center][align=left]

try..catch: 异常处理的第二种方式,自己处理异常
格式:
try{
可能产生异常的代码
}catch(异常类名 变量名) {
异常处理的逻辑
一般会记录到日志中
}catch(异常类名 变量名) {
处理异常
}...
[Java] 纯文本查看 复制代码
[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]public class Demo03Finally {[/size][/font][/align][/align][align=center][font=微软雅黑][size=3] [/size][/font][/align][align=center][align=left][font=微软雅黑][size=3]    public static void main(String[] args) {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        String s = "C:\\an.txt";[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        try {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            readFile(s);[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        } catch (IOException e) {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            e.printStackTrace();[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            //System.err.println(e.toString());[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        } finally {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            //无论是否出现异常,都会执行[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            System.out.println("资源释放");[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        }[/size][/font][/align][/align][align=center][font=微软雅黑][size=3] [/size][/font][/align][align=center][align=left][font=微软雅黑][size=3]        System.out.println("继续运行");[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]    }[/size][/font][/align][/align][align=center][font=微软雅黑][size=3] [/size][/font][/align][align=center][align=left][font=微软雅黑][size=3]    private static void readFile(String s) throws IOException {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        if (!s.equals("C:\\a.txt")) {[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]            throw new IOException("文件路径不正确");[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        }[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]        System.out.println("打开文件");[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]    }[/size][/font][/align][/align][align=center][align=left][font=微软雅黑][size=3]}
注意:
try中可能会抛出多个异常对象,那么就可以使用多个catch来处理
如果try中产生了异常,那么就会跳过try中剩余的代码,执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行之后的代码
如果没有产生异常,那么直接执行之后的代码
如果try中代码有运行期异常且没有对应的catch进行捕获,那么,将会交给JVM默认处理,并且try..catch之后的代码将不会再执行
java.lang.Throwable类中定义了3个异常处理的方法
String getMessage():返回此throwable的简短描述
String toString():返回此throwable的纤细信息字符串
void printStackTrace():JVM打印异常对象,默认使用此方法,信息最全面,该方法不会终止程序
注意事项:
一、处理多个异常
多个异常分别处理,使用多个try..catch组合分别捕获异常
多个异常一次捕获,多次处理,使用try + 多个catch
catch里边定义的异常变量,如果有父子类关系,那么子类的异常变量必须写在上边,否则会报错
父类异常多态接收
二、子父类继承重写
抛出父类相同的异常
抛出父类异常的子类
不抛出异常
父类没有抛出异常,子类重写父类该方法时也不可能抛出异常
此时子类产生该异常,只能捕获,不能声明抛出
即父类异常什么样,子类也就什么样
线程安全 线程状态
线程安全
如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全
线程同步
Java中提供了同步机制(synchronized)来解决,有三种方式完成同步操作:
1. 同步代码块
格式:
synchronized(同步锁){
     需要同步操作的代码
}
同步锁:
对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁
1. 锁对象 可以是任意类型
2. 多个线程对象 要使用同一把锁
2. 同步方法
格式:

[AppleScript] 纯文本查看 复制代码
public synchronized void method(){
   可能会产生线程安全问题的代码
}
3. 锁机制
java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock() :加同步锁。
public void unlock() :释放同步锁。
线程状态
NEW
至今尚未启动的线程处于这种状态
新建状态 创建了线程对象 但是还没有调用strat()方法
RUNNABLE
正在 Java 虚拟机中执行的线程处于这种状态
正在执行的代码,可能分配到了CPU时间片,也可能没分配到,有系统决定
               
BLOCKED
受阻塞并等待某个监视器锁的线程处于这种状态
线程A与线程B使用同一把锁,如果线程A拿到了锁,那么线程B就进入了锁阻塞状态
WAITING
无限期地等待另一个线程来执行某一特定操作的线程处于这种状态
一定是在有同步锁对象的时候,调用可wait等不传递时间参数的方法,进入无限等待,只能依靠另一个同步线程完成唤醒
TIMED_WAITING
等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态
两种情况
1:sleep  进入“休眠” 等待时间到了就结束,在等待时间内的状态就是计时等待状态。
2:一定是在有同步锁对象的时候,调用可wait等传递时间参数的方法,进入计时等待,如果在这段时间内,另一个同步线程完成唤醒,那么就唤醒。否则那么就等到这段时间结束 就醒了,进入等待 ,醒之前时间内的状态就是计时等待
               
TERMINATED
已退出的线程的处于这种状态或者终止状态
线程run方法执行完毕 或者遇到未知问题结束的时候
在给定时间点上,一个线程只能处于一种状态。这些状态是虚拟机状态,它们并没有反映所有操作系统线程状态。
                       
                                                

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马