Day 20
0321
hashMap和hashtable的区别
1、两者在api的操作上基本上一样,没有太大的区别
2、hashMap允许空键空值(null键只能出现一次),hashtable不允许出现null键null值
3、hashMap线程不安全,hashTable线程安全
4、Hashmap效率高些,hashtable更低
treeMap
红黑算法
entry
key value left right black
treemap底层是采用红黑树算法来进行数据的查找,红黑树的每一个节点都是一个entry,里面包含了key value left right color ,root节点默认是黑色的 ,entry是根据k来进行排序的,entry节点包含的内容为value。
entry排序是按照key来排的,key是放在treeset,entry的key要比较大小根据比较器comparator来进行判断的
size:红黑树的节点个数
线程
线程概述
理解进程和线程
进程:运行中的应用程序称为进程,进程拥有CPU和内存资源
线程:线程是进程中的一段代码,一个进程 可以有多段代码(一个进程包含多个线程),线程本身不拥有资源的。共享所有进程的资源
多进程:在操作系统中能同时运行多个任务(qq,eclipse)
多线程:在同一个应用程序中,有多个顺序流(多段代码)在同时执行(qq视频,发图片)
代码的理解
开启这个程序的时候,在操作系统里面产生一个进程,进程是main方法开始的,当执行main方法的时候,在当前进程里面开启一个线程(主线程),main调用method1方法,main进入到methd1继续执行代码,main里面的其他代码无法马上执行,必须等待method1执行完 了再回来执行main的输出语句。
整个程序从开始到结束都只有一个线程,单线程程序,执行路径只有一条。
单线程:一个任务完了继续后面任务,不能同时执行,所花的时间所有任务加在一起。
进程:
1、把应用程序代码放在内存中的代码区,代码放在方法区并没有马上执行,但是这个时候说明一个进程正在准备开始,进程产生,但是没运行,进程其实是一个静态的概念。
2、进程的执行指的是进程里面的主线程开始执行的。main方法的执行,在机器上运行任务的全都是线程。
windows操作系统时多进程的系统,同时可以执行很多的线程,Linux、Unix
Dos是单线程系统
思考?多线程表示多个任务同时执行,CPU如何来分配资源*
Cpu运行速度是非常快,一秒钟几亿次,所以将CPU的运行时间分为一个一个的小片段,每个任务都可以在一个时间片段里面执行一次,如果在当前片段里面没有执行完,其他任务执行完了继续执行。因为速度很快,给我们的感觉同时在执行。
实际上 在一个时间节点上只有一个任务在执行
如果你的电脑是双CPU、多核、实现真正多线程
java是如何去创建线程
4种:
1、继承java.lang.Thread类,当前类就表示多线程类
2、实现Runnable接口,也可以表示多线程类
3、实现Callable接口,也可以实现多线程
4、线程池
Thread.currentThread()可以获取到当前执行的线程。通过它获取线程的信息(名字、id、其他)
线程体,多线程任务都在run里面执行
public void run(){
}
==========================================
第一种:
继承Therad类
1.产生一个线程对象
2.启动线程
(创建一个构造方法,实现区分多个线程的运行)
线程体
=====================================
第二种
实现Runnable
重新new一个Thread类,将当前线程放进去
==============================================
(创建一个构造方法,实现区分多个线程的运行)
多线程任务进行
获取当前线程的名字
Thread。currentThread()。getName()
启动线程start,为什么调用它而不是调用run?
api提出start才是启动线程方法,run线程体,直接调用相当于直接调用方法。产生多线程程序start,将线程放入到线程组(线程队列 先进先出),接下来在调用本地方法start0(),通知虚拟机来执行线程,虚拟机默认会调用线程的run方法来执行。所以一定执行start方法。
线程优先级的问题
java提供了一个线程调度器来监控程序中启动后进入就绪状态的线程。线程调度器会根据线程优先级来判断先调度哪个线程执行。
线程优先级用数字1-10表示,值越大优先级越高,默认缺省值为5(主线程默认都是5)
程序的运行结果还是由虚拟机来安排,无法预知运行后的结果,线程优先级高低只是一个参考值,相对的结果,理论上是具有高优先级的程序占有更多的CPU使用权,但是有时候并不是这样的结果。
================================
prioity:优先级
打印当前线程优先级
setPrioity();设置优先级
getPrioity();获取优先级
线程的生命周期
五种状态
1、新建
2、就绪
3、运行
4、阻塞
1、等待阻塞
2、同步阻塞
3、其他阻塞
5、死亡
其他阻塞:
sleep()、join()、I/O操作
线程主动让出执行权:yield
sleep:Thread.sleep() sleep属于Thread静态方法,单位是毫秒,一旦调用sleep,当前线程处于睡眠状态,当睡眠时间过去后马上恢复就绪状态,此方法会造成线程阻塞
代表当前线程休眠
join:合并某个线程,如果有两个线程A\B,A必须等待B运行完了才能继续往下运行,我们可以调用join来完成这项工作。合并过后就相当于以前直接调用方法()
yield:在多线程运行过程中,当前抢到CPU资源的线程想让出使用权,调用yield方法马上就让出使用权变成就绪状态,但是还可能被jvm分配使用权。在实际开发中,无法保证yield让步。
线程的同步
什么是同步
多个线程同时运行,有时候线程之间要共享数据,一个线程需要其他线程的数据,否则就不能保证程序的运行结构。
并发 同一个时间点,多个线程访问统一资源
==共享资源(临界资源)*==多个线程共享数据成为共享资源,或者成为临界资源。
==线程同步:==同步就是协同步调的意思,按照预先先后顺序进行执行,先抢到资源的线程先执行,后抢到资源的线程后执行,两个线程相互配合,共享数据。
==线程互斥==对个线程在共享某一个变量,而且都对变量有修改,如果不考虑在运行过程中 用户协调问题,就会出现数据不一致,数据安全问题。
在java中要实现多线程同步:
1、同步块
2、同步方法
3、volatile关键字
同步块:相当于自动加上内置锁,实现同步操作
语法:
synchronized(){
//代码只能在同一时间一个线程访问
}
同步方法:
在方法访问修饰符后加上synchronized
public synchronized void add(){
}
在java中每个对象都会有一个内置锁,当你使用synchronized关键字的时候,内置锁会保护整个方法,在调用方法前需要获取到内置锁,否则处于等待状态。
volatile关键字:
给局部变量的访问提供了一种免锁机制,一个变量使用它来修饰告诉虚拟机该域可能会被其他线程更新,每次使用当前值得时候,都要重新计算一下。默认的值保存寄存器,所以线程互斥就是直接取寄存器的数据,volatile不会提供任何原子操作,也不能用final来修饰。
=================================================
其他阻塞介绍及使用:
Thread.sleep
代表当前线程休眠
========================================
结束子线程方法1:(一般使用方法一)
子线程循环
while(boo=true)
主线程睡眠后结束子线程
方法二:
主线程调用interrupt表示将当前运行的线程打断
线程被打断之后会抛出异常
子线程抛异常之后要写return
================================================
join 合并线程
将子线程合并到主线程中
子线程先执行完了 再执行主线程
线程名。join();
==================================================
IO阻塞
io阻塞让出cpu,让主线程运行
子线程输入输出,主线程运行完毕后子线程才开始运行
==================================================
yield
让出资源(资源让出来的话,并不是说别的线程一定会使用当前资源)
主线程:
子线程
Thread。yield;
===========================================
线程同步
同步块使用
未使用同步块
使用同步块:
synchronized(this){
}
this表示当前对象
========================
同步方法的使用
volatile关键字使用
可能会遇到的情况:
使用static修饰
============================================