java多线程
创建线程的第一种方式:继承Thread类
步骤:
1 定义类继承Thread
2 复写Thread类中的run方法
目的:将自定义的代码存储在run方法中,让线程运行。
3 调用线程的start方法,该方法有两个作用,启动线程,调用run方法。
默认名称:Thread-编号 从0开始
static Thread currentThread():获取当前线程对象
getName():获取线程名称
****简单的卖票程序。
第二种方法:创建线程的第二种方式:实现runnable接口
步骤:
1. 定义类实现Runnable接口
2. 覆盖Runnable接口的run方法。
3. 通过Thread类建立线程对象。
4. 将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
5. 调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
两种方式区别:
继承Thread:线程代码存放在Thread子类run方法中
实现Runnable:存在接口的子类的run方法。
synchronized(对象)
{需要被同步的代码}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
同步的前提:
1 必须要有两个或者两个以上线程。
2 必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程都需要判断锁,较为消耗资源,
同步函数的锁是this
如果同步函数被静态修饰后,使用的锁是什么呢?
静态的同步方法使用的锁是该方法所在类的字节码文件对象。Ticket.class
单例设计模式:饿汉式,懒汉式(在多线程时)
1.延迟加载 2低效 3锁为字节码文件对象
多线程-死锁:例子:同步中嵌套同步,锁不同
等待唤醒机制。线程池。
wait()
notify()
notifyAll()
为什么这些操作线程的方法要定义Object中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。不可以对不同锁的的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。因此任意对象的方法定义在Object中。
生产者消费者例子:JDK1.5新特性
Lock 替代synchronized condition await signal signalAll
替代wait notify notifyAll
停止线程的方法:可以调用interrupt,run方法结束
守护线程:t.setDaemon(true) 后台进程,前台结束后自动结束
join()等待线程终止,抢夺CPU执行权
优先级 setPriority(1,5,10)
yield方法:暂停当前正在执行
线程组概念
-----------------------------------------------------------------------------------------------------
Java API:
具体查文档
String
StringBuilder:方法调用链
基本数据类型包装类
----------------------------------------------------
集合框架: Collection顶层
为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式都有不同。
这个存储方式称之为:数据结构
List:元素是有序的,元素可以重复。因为该集合体系有索引。
特有方法:带角标的方法。
ArrayList:底层使用的数据结构是数组结构。查询速度很快。但是增删稍慢。线程不同步
1. 添加元素 add 存储的是引用
2. 获取个数 .size();
3. 删除元素 remove clear清空
4. 判断元素 contains
交集:retainAll
removeAll
迭代器:iterator
获取迭代器,用于取出集合的元素。
List集合特有的列表迭代器:ListIterator是Iterator的子接口
在迭代时,不可以通过集合对象的方法操作集合中的元素。只能用迭代器的方法操作元素。
LinkedList:底层使用的是链表数据结构,增删速度快,查询速度慢.add get和remove的区别。获取时一个不删一个删。
1.6后提供 peek poll 空列表不抛异常返回空
Vector:底层是数组数据结构,线程同步。被ArrayList替代。枚举是Vector特有的取出方式,被迭代器出现。
------------------------------------------------
Set:元素是无序的,元素不可以重复。
HashSet:底层数据结构是哈希表
保证唯一性:hashCode和equals方法。复写注意格式。线程是非同步的。
TreeSet:可以对Set集合中的元素进行排序。
添加自定义对象:implements Comparable强制让学生具备比较性
。底层数据结构是二叉树,红黑树。保证惟一性:compareTo方法
return 0;
TreeSet排序的第一种方式:让元素具备比较性,称为自然顺序。
comparable 中的compareTo方法。实现Comparable
TreeSet的第二种排序方式。
当元素自身不具备比较性时。或者不是需要的时候。
这时让集合本身具备比较性。定义了比较器,将比较器对象作为参数传递给构造函数。comparator 接口,复写compare方法
**排序时:当主要条件相同时,排序次要条件
泛型:JDK1.5版本以后出现新特性,用于解决安全问题,是一个安全机制。
ArrayList<String> al = new ArrayList<String>();
好处:
1. 将运行时期出现问题ClassCAstException,转移到编译时期。
2. 避免了强制转换的麻烦。<>用来接收泛型的。
Iterator<String> it=iterator();
泛型类:class Util<T>{}
什么时候定义泛型类,当类中要操作的引用数据类型不确定的时候
。早期定义Object来完成扩展。现在定义泛型来完成扩展。
泛型方法:public <Q> void show(Q q)
泛型定义在接口上
泛型限定:<?> <? extends Person> <? super E>
void printColl(Arraylist<..> al)
-------------------------------------------------
Map集合: 该集合存储键值对。一对一对往里存。而且要保证键值的唯一性。
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null。该集合是线程同步的。jdk1.0
|--HashMap:底层是哈希表数据结构,允许使用null值和null键。该集合是线程不同步的。jdk1.2
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。和Set很像。Set底层就是使用了Map集合。
HashMap:新的值替换旧的值。
map集合的两种取出方式:
1. keySet:将map中的所有的键存入到Set集合。因为set具备迭代器。根据所有的键get对应的值。
2. entrySet:<Map.Entry<K,V>> 泛型嵌套
//Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。
map扩展知识:读懂HashMap<String,HashMap<String,String>
工具类:
Collections.sort(List list)
.max(Collection c)
.binarySearch: 有序集合
.fill 替换
.replaceAll替换
.reverse 反转
.reverseOrder 逆转比较
SynList:synchronizedList()返回线程安全
shuffle 随机
Arrays:操作数组
asList()将数组变成list集合**不可以使用集合的增删方法。因为长度固定。
集合变数组:Collection中的方法toArray
1.5新特性:
高级for循环
for(数据类型 变量名:被遍历的集合(Collection)或者数组)**
可变参数:show(int...arr)
import static java.util.Arrays.*; 静态导入。可以不写类名
---------------------------------------------------
其它对象
System:
获取系统属性信息:getProperties()
java -Dhaha=qqqqq SystemDemo
Runtime: 单例设计模式
exec(...) 双斜杠
Date:.util.*;
java.text.*;
new Date()当前时间。
Calender:
Math
.Random 0-1的随机数