多线程
一、线程和多线程
1、线程的概念
- 进程:在程序要投入运行时,系统从程序入口开始按语句的顺序(包括顺序、分支和循环结构)完成相应指令直至结尾,再从出口退出,整个程序结束。
- 线程是比进程更小的执行单位
- 线程是进程的一部分
2、线程的结构
- 线程的结构
线程的结构
在Java中,线程由以下3部分组成。
·虚拟CPU,封装在java.lang.Thread类中,它控制着整个线程的运行。
·执行的代码,传递给Thread类,由Thread类控制按序执行。
·处理的数据,传递给Thread类,是在代码执行过程中所要处理的数据。
3、线程的状态
- 线程是通过包java.lang中定义的类Thread来实现的
- Thread类本身只是线程的虚拟CPU
- 线程一共有4种状态,分别是新建(New)、可运行状态(Runnable)、死亡(Dead)及阻塞(Blocked)。
- 可运行状态
线程已经启动,处于线程的run()方法之中。
可以运行但没在运行的线程都排在一个队列中,这个队列称为就绪队列。
调用线程的start()方法可使线程处于可运行状态。 - 死亡
线程死亡的原因有两个:一是run()方法中最后一个语句执行完毕,二是当线程遇到异常退出时便进入了死亡状态。 - 阻塞
一个正在执行的线程因特殊原因,被暂停执行,就进入阻塞状态。阻塞时线程不能进入就绪队列排队,必须等到引起阻塞的原因消除,才可重新进入队列排队。引起阻塞的原因很多,不同原因要用不同的方法解除。sleep()和wait()是两个常用的引起阻塞的方法。
二、创建线程
1、继承Thread类创建线程
- 创建线程有两种方法,一种是定义一个继承Thread类的子类,另一种是实现Runnable接口。
- 用Thread类的子类创建线程的过程包括以下3步。
1)从Thread类派生出一个子类,在类中一定要实现run()。
class Lefthand extends Thread {
public void run(){…} //线程体
}
2)然后用该类创建一个对象。如
Lefthand left=new Lefthand( );。
3)用start()方法启动线程。如left.start( );。 - 用Thread类的子类创建线程
2、实现Runnable接口创建线程
- Runnable是Java中用以实现线程的接口
- Runnable接口中只定义了一个方法就是run()方法,也就是线程体。
- 用Runnable接口实现多线程时,也必须实现run()方法,也需要使用start()启动线程
- 编写线程体
public class xyz implements Runnable {
int i;
public void run( ) {
while (true) {
System.out. println (" Hello " + i++);
}
}
}
- Runnable接口创建线程
三、线程的基本控制
1、线程的启动
- API中提供了以下有关线程的操作方法。
·start():启动线程对象,让线程从新建状态转为就绪状态。
·run():用来定义线程对象被调度之后所执行的操作,用户必须重写run( )方法。
·yield():强制终止线程的执行。
·isAlive():测试当前线程是否在活动。
·sleep(int millsecond):使线程休眠一段时间,时间长短由millsecond决定,单位为ms。
·void wait():使线程处于等待状态。
2、线程的调度
- 线程调度通常是抢占式
- 每个线程都有一个优先级,Java的线程调度采用如下的优先级策略。
·优先级高的先执行,优先级低的后执行。
·每个线程创建时都会被自动分配一个优先级,默认时,继承其父类的优先级。
·任务紧急的线程,其优先级较高。
·同优先级的线程按“先进先出”的调度原则。 - Thread类有3个与线程优先级有关的静态量,分别如下。
·MAX_PRIORITY:最高优先级,值为10。
·MIN_PRIORITY:最低优先级,值为1。
·NORM_PRIORITY:默认优先级,值为5。 - java.lang.Thread类中有关优先级的几个常用方法如下。
·void setPriority(int newPriority):重置线程优先级。
·int getPriority():获得当前线程的优先级。
·static void yield( ):暂停当前正在执行的线程,即让当前线程放弃执行权。 - 调度
public class Xyz implements Runnable {
public void run( ) {
while(true) {
…… //执行若干操作
//给其他线程运行的机会
try{
Thread.sleep(10) ;
}catch(InterruptedException e) { }
}
}
}
3、结束线程
线程运行完
- interrupt( )方法中断线程的执行。
- Thread类中的静态方法currentThread( )来引用正在运行的线程。
- isAlive()来获取一个线程是否还在活动状态的信息。
4、挂起线程
- sleep()方法用于暂时停止一个线程的执行。
- wait()方法导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,才能唤醒线程。
- join()方法将引起现行线程等待,直至join()方法所调用的线程结束。
四、线程的互斥
- 栈具有“后进先出”模式
- 栈示例
class Stack{
int idx = 0 ;
char data[ ] = new char[6];
public void push (char c){
data[idx] = c ;
idx ++ ;
}
public char pop(){
idx --;
return data[idx] ;
}
}
- 在Java语言中,有两种方法可以实现“对象互斥锁”。
·用关键字volatile来声明一个共享数据(变量)。
·用关键字synchronized来声明操作共享数据的一个方法或一段代码。 - 锁定标志
class stack {
int idx = 0 ;
char data[ ] = new char[6] ;
public void push (char c ) {
synchronized (this) { // 增加同步标志
data[idx] = c ;
idx ++ ;
}
}
}
synchronized( )语句的标准写法为:
public void push (char c) {
synchronized ( this ) {
…
}
}