1.概念:程序:静态代码指令
进程:代码的动态执行过程,每个进程一个方法区和堆
线程:程序内部的一条执行路径,每一条线程各自有栈和计数器,共享堆和方法区
单核CPU:假的多线程,执行一个挂起多个
多核CPU:Java文件执行,main主线程、垃圾回收线程、异常处理线程同时工作
并行:多个CPU做多个任务
并发:一个CPU做多个任务
单核CPU同时执行多个任务所需的时间比依次执行更慢
2.创建与使用:1.继承于Thread类的子类,重写Tread类中的run方法,创建对象于主线程,调用start方法(start方法的两个作用:启动当前线程;调用当前线程的run方法)
2.创建一个实现了Runnable接口的类,这个类去实现Runnable中的抽象方法run(),去主程序中创建类的对象,将此对象作为参数传入Thread构造器中,创建一个Thread类的对象,通过Thread的对象调用Thread方法。(调用的是Thread类中的start,但Thread中的start调用的是Runnable中的方法,二次调用)
3.比较:如果存在父类,或者存在共享数据,倾向于选择Runnable(但继承性,且不用加static);Thread本身重写了Runnable,自己·重写run实现二重覆盖。
*一个线程只能start一次,解决:再new一个
*不能直接调重写后的run方法,因为这样就不是多线程了
*Thread类中的常用方法:start:启动;调用run
run:重写并声明操作
currentThread():静态方法,返回执行当前代码的线程
getName():获取当前线程的名字
setName():设置当前线程的名字(还可以使用构造器改名)
yield():释放当前CPU的执行权,但不一定会切换执行进程
join():在线程a中调用线程b,此时线程a进入阻塞状态,直到线程b完全执行完毕,线程才结束阻塞状态
sleep(long millitime):让当前线程中止指定毫秒数,在指定时间内,当前线程是阻塞状态
isAlive():判断当前线程是否存活(Boolean型)
2.线程的调度:
优先级设置从统计概率上来讲会更早执行完毕,但在实际操作中不一定发生,甚至可能相反
一:时间片:
二:抢占式:高优抢低优
MAX, MIN,NORM(默认)
getPriority():获取当前线程的优先级
setPriority(int p):设置优先级
生命周期:JDK用Thread.State类定义了线程的状态
新建:造完线程就是新建
就绪:调用start就是就绪,但CPU不一定立即执行,所以不是运行
运行:线程开始运行,失去CPU资源后再次进入就绪状态
阻塞:sleep方法,join(),等待同步锁,wait(),suspend(),阻塞不是最终状态
死亡:完成了使命,或者异常中断或强制中断stop
同步:线程安全问题:同步锁锁死正在执行的线程,保证没有同时参与操作,即使当前线程受阻塞也无法改变
- 方式:一,同步代码块synchronized
1. 操作共享数据的代码即为需要被同步的代码
2. 共享数据:多个线程共同操作的变量。
3. 同步监视器:即锁,可以是任何一个类的对象,多线程共用一把锁(类也可以充当对象;若this指的对象唯一,也可以考虑)
弊端:速度减慢,只有一个线程执行同步代码,相当于单线程,效率减慢
二,同步方法:如果操作共享数据的代码完整地声明在一个方法中,可以将此方法声明为同步方法 在返回值类型前面加上synchronized
*同步方法也需要监视器,但不用显示声明,非静态为this,静态为当前的类
*对懒汉式加以改进
If(instance==null){
Synchronized(类名){
if(instance==null){
Instance=new ……;
}
}
}
Return instance;//双重判断提高线程效率,可能在开始会有多个线程同时进入第二个判断,但后面的线程会在声明后被挡住
三.Lock锁:lock lock();lock unlock()
*需要手动解除,但更加灵活
四.Callable接口:重写call接口,可以跟exception,但是类本身没有继承thread类,所以没有start方法,需要借助Future接口中的FutureTask
(Future接口可以对具体的Runnable和Callable任务的执行结果进行取消、查询进程、获取结果,FutureTask是该接口唯一的实现类且实现了Runnable接口),同时还需要new一个Thread启动多线程:new Thread().start();
*Callable相对Runnable的优势:1.call()可以有返回值
2.call()可以抛出异常,被外面的操作捕获,获取异常信息
3.Callable支持泛型
五.线程池:提前创建好多个线程放入线程池中,使用时直接获取,用完后放回池中,避免频繁创建和销毁,实现重复利用
优势:提高响应速度;降低资源消耗;便于线程管理(方法在接口实现类中)
建立:使用Executors创建ExecutorService接口实现类的对象(多态)。
Execute:适用于Runnable接口;submit:适用于Callable接口;shutdown:关闭线程池
- 死锁:不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,形成线程的死锁。进入死锁状态后,不会出现异常和提示,所有线程都处于阻塞状态无法继续
*解决:专门的方法;尽量减少对同步资源的定义;尽量避免嵌套同步
通信:多个线程之间的交流(*只能在同步方法或同步代码块中使用,只有同步监视器才能调用相关关键字)
wait和notify/notifyAll:notify唤醒一个被阻塞的线程,优先唤醒优先级高的线程;wait使线程进入阻塞状态,同时释放线程握有的锁。