一、 线程基本概念
进程和线程的基础知识
进程:运行中的应用程序称为进程,拥有系统资源(cpu、内存)
线程:进程中的一段代码,一个进程中可以有多段代码。本身不拥有资源(共享所在进程的资源)
区别:1、是否占有资源问题
2、创建或撤销一个进程所需要的开销比创建或撤销一个线程所需要的开销大。
3、进程为重量级组件,线程为轻量级组件
多进程: 在操作系统中能同时运行多个任务(程序)
多线程: 在同一应用程序中有多个功能流同时执行
二、 线程创建与启动
创建方式: 1 继承java.lang.Thread类
2 实现java.lang.Runnable接口
三、 线程的状态控制
1、 新建状态2、就绪状态3、死亡状态4、阻塞状态
四、 线程的调度和优先级
1、线程的基本信息
方 法 | 功 能 |
isAlive() | 判断线程是否还“活”着,即线程是否还未终止。 |
getPriority() | 获得线程的优先级数值 |
setPriority() | 设置线程的优先级数值 |
setName() | 给线程一个名字 |
getName() | 取得线程的名字 |
currentThread() | 取得当前正在运行的线程对象,也就是取得自己本身 |
2、线程的优先级
1)优先级(共10级):
它们决定线程执行的先后次序(优先级高者先执行)并可以通过Thread类中的setPriority()和getPriority()方法来改变和获取优先级。典型的优先级码
Thread.MIN_PRIORITY (1级)
Thread.MAX_PRIORITY(10级)
Thread.NORM_PRIORITY(5级)
(2)调度规则
Java是不支持线程时间片轮换的调度模型,而采用的是线程优先级高低的抢占调度模型。具有高优先级的线程可以抢占低优先级线程运行的机会。高优先级的线程将始终获得线程执行时间。但是这也不是绝对的,java线程调度器有可能会调用长期处于等待的线程进行执行,所以不要依靠线程的高优先级抢占模型去完成某些功能。
Java线程调度器支持不同优先级线程的抢先方式,但其本身不支持相同优先级线程的时间片轮换。但是如果java运行时系统所在的操作系统(如windows2000)支持时间片的轮换,则线程调度器就支持相同优先级线程的时间片轮换。
五、 线程同步互斥
1、Java中线程利用Synchronized关键字的实现同步互斥
synchronized可以用来限定一个方法或一小段语句或整个类(该类中的所有方法都是synchronized方法)
将访问共享数据的代码设计为synchronized方法
由于可以通过 private 关键字来保证数据对象只能被方法访问,所以只需针对方法提出一套同步锁定机制。通过synchronized 方法来控制对类中的成员变量(共享数据)的访问。
编写线程安全的代码会使系统的总体效率会降低,要适量使用
只有某一个线程的synchronized方法执行完后其它线程的synchronized方法才能被执行。
当前时间,只有一个线程访问被锁定的代码段,但不能保证其他线程去访问其他没有被锁定的代码段。因此所有对共享资源进行操作的代码段都应该加锁。
对数据库操作时,修改数据的线程要加锁,而读数据的线程可以不加锁
2、如何避免出现死锁
wait是Object类的方法,它的作用是拥有互斥锁的线程放弃锁的使用权,进入wait池进行等待,那么互斥锁就有可能被其他线程获得以执行其他任务。
notify也是Object类的方法,它的作用是从wait池中唤醒一条正在等待的线程进入就绪状态,被唤醒的这条线程就很可能重新获得cup和互斥锁来完成它的任务。
notifyAll和Notify很相似,它是从wait池中唤醒所有正在等待的线程进入就绪状态。
需要注意的是以上三个方法都只能在synchronized方法中应用,否者会出现下面的异常信息:IllegalMonitorStateException:current thread not owner。