- Set接口及其实现类
- set是元素无序并且不可重复的集合,被称为集
- HashSet ----哈希集,是set的一个重要实现类
List 为有序的
Set 为无序的
- 循环遍历Set中的元素
- foreach
- iterator 迭代器 </br>
<font color= "red">不能像List方法那样调用他的get()方法 </font>
因为Set本身是无序的,不可能去查询位置上的某个元素 </br>
Set中添加某个对象,无论添加多少次,最终只会保留一个该对象的引用,并且保存的是第一次添加的那个
Set中可以添加NULL对象
-
Map接口
- Map接口提供了一种映射关系,其中的元素是以键对值(key - value)的形式存储的,能够实现根据key快速查找value
- Map中的键值对是以Entry类型的对象实例形式存在
- 键(key)不可重复, value值可以
- 一个value值可以和很多key值形成映射关系,但是一个key值能能对应一个value值
- Map接口提供了分别返回key值集合、value值集合以及 entry(键值对)集合的方法
-
Map支持泛型,形式为Map<K,V>
k为Key值的类型,v为value值的类型 - HashMap类
- HashMap类是Map中的一个重要的实现类,也是最常用的,基于哈希表实现
- HashMap中的entry对象是无序排列的
- key值和value值都可以为null,但是一个HashMap只能有一个key值为null的映射(key值不可以)
indexOf(Object o) 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
lastIndexOf(object o) 返回此列表中最后一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。- 泛型不能使用基本类型,若果要使用,只能用基本类型的包装类
- byte ---- Byte
- short ----- Short
- int ----- Integer
- long ---- Long
- float -----Float
- double ----- Double
- char ----- Character
- boolean ------ Boolean
是JAVA集合框架中用来操作集合对象的工具类
也是JAVA集合框架的成员
Collections中定义了一个sort()方法,用来对集合进行排序要用Collections.sort()方法进行排序,必须实现Comparble接口
Comparble---------默认比较规则
<font color=red> Compartor---------临时比较规则 </font> -
Comparble接口------可比较的
- 定义该接口表示:这个类的大小可以比较大小,可以进行自然排序
- 定义了默认的比较规则
- 其实现类需实现compareTo()方法
- compareTo()方法返回正数代表大,负数代表小,0代表相等
- Compartor-------比较接口工具
- 用于定义临时比较规则,而不是默认比较规则
- 其实现类需要实现compare()方法
- Comparbl和Compartor都是JAVA集合框架的成员
-
创建线程的第一种方法:
- 1.定义类继承Thread
- 2.重写Thread中的run方法
目的:将自定义的代码存储在run中,让线程执行 - 3.创建一个继承了Thread线程类对象,相当于创建了一个线程
- 4.调用线程的start()方法
- 该方法有两个作用
- 1.启动线程
- 2.调用run方法
线程是一个子任务,CPU以不确定的方式,或者说是以随机的时间来调用线程中的run方法,所以
在使用多线程技术时,代码的运行结果与代码执行顺序或调用顺序是无关的。
因为多个线程都在获取CPU的使用权,CPU执行到谁,谁就执行
在某个时刻,只能有一个程序在运行
CPU在做着快速的切换,以达到看上去是同时运行的效果
我们可以形象的把多线程的运行形容为互相在抢夺CPU的资源
这就是多线程的一个特性:随机性线程都有自己默认的名称
Thread-编号 该编号从0开始
static Thread currentThread():获取当前线程对象
getName():获取线程名称设置线程名称:setName或者构造函数传值super关键字
-
创建线程的第二种方式:
- 1.定义实现Runnable接口。
- 2.覆盖Runnable接口中的run方法。
将线程要运行的代码存储在run方法中 - 3.通过Thread类建立线程对象 。
- 4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
为什么要将Runnable接口的子类对象传递给Thread的构造函数。
因为自定义的run方法所属对象是Runnable接口的子类对象
所以要让线程去执行指定对象的run方法。 - 5.调用Thread类对象的start方法开启线程并调用Runnable接口子类的run方法。
实现方式和继承方式有什么区别?
实现方式的好处:避免了单继承的局限性
在定义线程时,建议使用实现方式。JAVA对于多线程的安全问题提供了专业的处理方式
就是同步代码块synchronized(对象){ //需要被同步的代码块 }
对象如同锁,持有锁的线程可以再同步中执行
没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁
如public class Ticket implements Runnable{ private static int tick = 200; Object obj =new Object(); public void run(){ while (true){ synchronized (obj) { if (tick > 0) { try { Thread.sleep(5); //延迟操作5毫秒 } catch (Exception e) { } System.out.println(Thread.currentThread().getName() + "----" + tick); tick--; } } } }
}
``` java
public class Test {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
t2.start();
}
}
同步的前提:
- 必须要有两个或者两个以上的线程。
- 必须是多个线程使用一个锁
必须保证同步中只有一个线程在执行
优点:解决了线程的安全问题
缺点:多个线程都需要判断锁,较为消耗资源
同步的另一种方法-------同步函数
只要将synchronized作为函数的修饰符就行了
函数都需要被对象调用,那么函数都有一个所属对象引用,就是this。
所以同步函数使用的锁是this。
同步函数改写了Ticker类
public class Ticket implements Runnable{
private static int tick = 200;
//Object obj =new Object();
public void run(){
while (true){
this.show();
}
}
public void show(){
if (tick > 0) {
try {
Thread.sleep(5);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + "----" + tick);
tick--;
}
}
}
通过验证,同步函数被静态修饰后,使用的锁不再是this,因为静态方法中也不可定义this
静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class。
静态的同步方法,使用的锁是该方法所在类的字节码文件对象 类名.class
java线程间通讯
java线程间通讯,其实就是多个线程在操作同一个资源,只是操作的动作不一样
wait:
notify();
notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以都使用在同步中,因为同步中才有锁
为什么这些方法要定义在Object类中呢?
因为这些方法在操作同步中线程时,都<font color =red >必须要标识它们所操作线程持有的锁</font>
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒
不可以对不同锁中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁
而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
JDK1.5中提供了多线程升级的解决方案
将同步的synchronized替换成现实Lock操作
将Object中的wait,notify,notifyAll替换成了Condition对象。
该对象可以Lock锁,进行获取
停止线程
stop方法已经过时
只有让run方法结束,线程才会结束
只要控制住循环,就可以让run方法结束,也就是线程结束
当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对线程冻结进行清楚
强制让线程恢复到运行状态中来,这样子就可以操作标记让线程结束
Thread提供了interrupt()方法。
如:
StopThread类
import Book.Run;
/**
* Created by asus on 2016/11/18.
*/
public class StopThread implements Runnable {
private boolean flag = true ;
public synchronized void run(){
while (flag){
try{
this.wait();
}catch(InterruptedException e ){
//线程被强行打断后,就会报异常,这时就可以通过操作flag让while循环停止,从而结束线程
System.out.println(Thread.currentThread().getName()+".....Exception");
flag =false;
}
System.out.println(Thread.currentThread().getName()+"....run");
}
}
}
StopThreadDemo类
public class StopThreadDemo {
public static void main(String[] args){
StopThread st =new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
int num = 0 ;
while(true){
if (num++ ==60){
t1.interrupt();//强行打断冻结的线程,让线程运行
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"....."+num);
}
System.out.println("over");
}
}
JAVA I/O 输入输出流
1.解决编码问题
2.file类的使用
3.RandomAccessFile的使用
4.字节流的使用
5.字符流的使用
6.对象的序列化和反序列化
- 字节流抽象基类
- InputStream
- OutputStrea
-
字符流的抽象基类
- Reader
- Writer
<font color =red>
注:
由这4个子类派生出来的子类名称都是以其父类名作为子类名的后缀
如:InputStream的子类FileInputStream.
Reader的子类FileReader</font>
- Writer
- writer()方法:写入字符串
- flush()方法:刷新流数据的缓冲,将要写入的字符串写入到指定文件中
- close()方法:关闭该流,但是会先刷新一次,关闭后无法进行流操作