多线程
-
线程类Thread介绍
- 构造方法
- public Thread();
- public Threadd(String name);//带有线程名字的构造
- public Thread(Runnable r);Runnable的构造
- public Thread(Runnable r,String name);
- 成员方法
- public String getName();//获取线程名字
- public void setName();//修改线程名字
- public void start();//开启线程
- public void run();//线程执行的任务
- 静态方法
- public static void sleep(long 毫秒值 );//让线程休眠
- public static Thread currentThead(); 获取到当前对象
- 构造方法
-
多线程原理
- 时序图
- 内存图
- 每个线程都拥有独立的栈,所有线程共享一个堆
-
新建线程方式二
- 创建实现类,实现Runnable接口
- 实现类重写run方法
- 创建实现类对象
- 创建Thread同时传入实现类对象
- 启动线程
-
两种创建线程的区别
- 一种是继承方式,另一种的实现方式
- 实现方式避免了单继承的不足
- 实现方式线程对象和任务对象是松耦合的,继承方式是紧耦合
- 实现方式可以让多个线程
-
匿名内部类创建线程
-
//继承方式 new Thread(){ @Override public void run() { //方法体 } }.start();
//实现方式 new Thread(new Runnable(){ @Override public void run() { //方法体 } }).start();
-
线程安全
-
原因
- 单线程永远不会有安全问题
- 多线程同时执行,执行同一个任务,操作同一个共享资源,才可能有安全问题
-
线程同步
- 当前线程没有执行完毕之前,其他线程不能执行
-
三种方式
-
同步代码块(最常用);
-
格式 synchronized(对象锁){
需要同步的代码
}
-
-
同步方法
-
格式
-
public synchronized void mathod(){
需要同步的代码
}
-
默认使用this作为对象锁
-
如果是静态方法,默认当前类的字节码文件作为对象锁
-
-
Lock锁
- 格式
- Lock lock = new ReentrantLock();
- lock.lock();//加锁
- 需要同步的代码
- lock.unlock();//解锁
- 格式
-
线程状态
- 新建状态(New)
刚刚创建的线程,还没有调用start方法 - 可运行状态(Runnable)
创建后的线程,调用了start方法 - 锁阻塞状态(Blocked)
线程需要锁才能执行,但是锁被其他线程持有 - 限时等待状态(Timed_waiting)
在线程中调用Thread.sleep(毫秒值)后 - 无限等待状态(Waiting)
- 线程如何进入Waiting(无线等待状态)
- 当前线程持有锁对象
- 调用锁对象的wait方法
- 当前线程自动释放锁对象,然后进入无限等待状态
- 其他线程如何唤醒Waiting状态的线程
- 其他线程必须持有锁对象(必须是刚刚无限等待那个线程释放的锁对象)
- 调用锁对象的notify方法
- 被唤醒后的线程不会立刻进入可运行状态,而是进入锁阻塞状态,直到再次持有锁对象
- 消亡状态(Terminated)
- 当线程的任务执行完毕
- 线程如何进入Waiting(无线等待状态)
待唤醒机制
- 等待唤醒机制(Wait和Notify)
Collection
- 集合
- 介绍: 是一种java中的容器
- 与数组的区别:
- 长度可变
- 只能保存引用类型
- 框架…
- 方法(7)…
- 迭代器
- 介绍:
- 帮助我们从集合中取出元素对象
- 迭代器属于Iterator类型
- 使用
Iterator it = 集合名.iterator();
while(it.hasNext()){
System.out.printl(it.next())l
}
- 注意
- NoSuchElementException 没有此元素异常
- ConcurrentModificationException 并发修改异常
- Java规定使用迭代器的过程中不能对集合进行增删操作,否则就抛出并发修改异常
- 迭代器的作用就是单纯的遍历!!!
- 原理
- 底层原理:指针实现的
- hasNext() 方法不会移动指针
- next() 方法会移动指针,并且取出指针移动经过的那个元素
- 增强for循环(FoeEach)
- 增强for循环是一种语法糖,简便格式,底层是迭代器
- 格式:
for(数据类型 变量名 : 集合/数组){
拿到变量名
}
- 介绍:
泛型
-
介绍:
- 是一种不确定的类型,由程序员在具体使用是才能确定
- 格式: …
-
好处
- 避免了强制转换的麻烦
- 避免了类型转换异常,转移到了编译时期,变成编译失败
-
定义和使用
//泛型类定义 public class Dog<E> { private E e; ``` public E getE() { return e; } public void setE(E e) { this.e = e; } ``` } //泛型类的使用 public class TestDog { public static void main(String[] args) { //1.使用泛型类 Dog<String> d1 = new Dog<String>(); d1.setE("aaa"); System.out.println(d1.getE()); ``` Dog<Integer> d2 = new Dog<Integer>(); d2.setE(111); System.out.println(d2.getE()); } ``` ------------------------------------------------- } //泛型方法的定义 public class Pig { public <T> void show(T t) { System.out.println(t); } } //泛型方法的使用 public class TestPig { public static void main(String[] args) { //1.创建对象 Pig p = new Pig(); //2.调用方法 p.<String>show("abc"); p.<Double>show(3.14); } } -------------------------------------------------- //泛型接口的定义 public interface MyCollection<E> { public abstract void setE(E e); public abstract E getE(); } //泛型类有两种确定泛型的方式 //a.实现类在实现接口时,确定泛型 class MyClass1 implements MyCollection<Integer>{ @Override public void setE(Integer integer) { } @Override public Integer getE() { return null; } } //b.实现类咋实现接口时,不确定泛型,实现类继续保留泛型 class MyClass2<E> implements MyCollection<E>{ @Override public void setE(E e) { } @Override public E getE() { return null; } } //此时MyClass2<E>就是一个泛型类,回到泛型的使用上
-
通配符
- ? 代表任意泛型
-
泛型的上下限
- ArrayList<?> 代表任意泛型的集合均可
- 上限: <? extends Animal>: 代表泛型必须是Animal本类或者子类
- 下限:<? super Cat>:代表泛型必须是Cat本类或Cat的父类
数据结构
- 概念;
- 容器中存放组织数据的一个结构
- 常见4+1的数据结构
- 堆栈结构: 先进后出(FILO)
- 队列结构:先进先出(FIFO)
- 数组结构:查询快,增删慢
- 链表结构:查询慢,增删快
- 红黑树结构:查询速度恐怖,增删慢的可怕
List接口
- 特点:
- 有序(存取顺序一致)
- 有索引
- 元素可重复
- List方法与实现类
- 拥有Collection接口的方法和迭代器
- 四个和索引相关的增删改查方法
- public void add(int index,E e);插入元素
- public E remove(int index);根据索引删除元素
- public E set(int index,E e);修改指定索引的元素
- public E get(int index);根据索引获取元素
- 实现类
- ArrayList: 底层是数组,无特有方法
- LinkedList: 底层是链表结构,8个特有方法
- Vector
Set接口
- 特点
- 无序(LinkedHashSet除外);
- 无索引
- 元素唯一
- 常用方法与实现类
- 拥有Collection接口中的方法和迭代器
- 特有方法: 无
- 实现类
- HashSet(无序):底层:哈希表.无特有方法
- LinkedHashSet(有序)底层:链式哈希表,无特有方法
- TreeSet
- 哈希表结构
- 哈希表结构 = 数组 + 链表 +红黑树(JDk1.8)
- 对象的哈希值(对象的"数组指纹")
- 调用对象的hashCCode方法获取对象的哈希值
- Java中的地址是假的,只是哈希值转换成了16进制
- 真正的地址:对象名中保存的就是真正的地址
- 但答应不出了,因为打印对象名会默认调用toString方法
- 不同对象的哈希值可能一样的
- 如: “abc” “acD” 都是96354
- 结论:哈希表结构如何保证元素的唯一性??
- 哈希表会比较新旧元素的哈希值,以及调用equals方法,只有哈希值相等,并且equals返回true,才判断元素重复
- 使用哈希表结构保存自定义类型的元素
- 使用哈希值结构保证自定义类型时,为了保证元素的的唯一性,需要重写自定义类型中的hashCode和equals方法(工具自动生成).
- 可变参数
- 指的是参数个数可以变化
- 格式:
- 数据类型…变量名
- 本质:
- 实际上可变参数就是数组
- 注意
- 一个方法最多只能有一个可变参数
- 既有可变参数,又有正常参数,那么可变参数必须写在最后面
Collections
-
介绍:
- 是一个工具类(所有方法都是静态的)
-
常用方法
- public static void shuffle(List <?> list);//打乱集合顺序
- public static void sort(List<?> list);//升序排列集合
- 规则:
- 如果元素是数值类型,按照大小升序
- 如果元素是字符类型,按照ASCII码值升序
- 如果元素是字符串类型,首先按照首字母ASCII码值升序,首字母一样按照次字母ASCII码值升序,依次类推
- 规则:
-
Comparator比较器排序接口
-
Collections.sort()(集合名,new Comparator<Integer){ //此方法称为比较方法 //返回值表示 //正数 表示前者大于后者 //0 表示前者等于后者 //负数 表示前者小于后者 public int compare(Integer o1, Integer o2) { //升序 前-后 //return o1-o2; return o2-o1; } });
-