Download presentation
Presentation is loading. Please wait.
1
西南科技大学网络教育系列课程 高级语程序设计(Java) 第八章 线程
2
线程及相关概念 程序:计算机高级语言编写的代码,静态,是应用程序的蓝本。
进程:是程序的一次动态执行过程,进程包括所要执行的指令和所需的系统资源,不同的进程所占用的系统资源相对独立。 线程:比进程更小的执行单位,自身不能自动运行,必须栖身于某一进程之中,由该进程触发执行,属于同一进程的线程共享该进程的系统资源。 多进程:系统中多个程序同时执行(多任务)。 多线程:程序(进程)中多个片断同时执行。
3
Java程序执行的过程 当JVM加载代码,发现main方法之后,就会启动一个线程,这个线程称作“主线程”,该线程负责执行main方法。 如果main方法中没有创建其他的线程,那么当main方法执行完最后一个语句,JVM就会结束Java应用程序。 如果main方法中创建了其他线程,那么JVM就要保证每个线程都有机会使用CPU资源。 JVM一直要等到主线程中的所有线程都结束之后,才结束Java应用程序。
4
线程的生命周期 线程的五个生命周期 新建:新建的线程处于新建状态。 就绪:在创建线程后,它将处于就绪状态,排队等待进程调用。
运行:线程获得CPU资源后,就进入运行状态,开始执行。 阻塞:在线程等待一个事件时(例如输入/输出操作),就处于阻塞状态。 死亡:线程不再具有继续运行的能力。 线程完成了自己的任务。 线程被强迫终止。
5
新建状态 就绪状态 阻塞状态 运行状态 死亡状态 线程生命周期示意图
6
线程的优先级和调度调度 当一个在就绪队列中排队的线程被分配到处理器资源而进入运行状态之后,这个线程就称为被“调度”或被线程调度管理器选中了。
线程调度管理器负责管理线程排队和处理器在线程之间的分配 在java系统中,线程调度依据优先级基础上的“先到先服务”原则。
7
Java虚拟机(JVM)中的线程调度器负责管理线程,调度器把线程的优先级分为10个级别。
优先级使用Thread类中的类常量表示。 static int MIN_PRIORITY 值为1 static int MAN_PRIORITY 值为10 static int NORM_PRIORITY 值为5 int getPriority() :返回线程的优先级。 void setPriority(int a)可以设置线程优先级。
8
线程的创建 创建线程有两种方法 继承Thread类 实现Runable接口 每个Java程序至少有一个叫做主线程的线程
Thread类的currentThread方法可以获取主线程(或当前线程)。 getName方法可以取得主线程(或当前线程) 的名字。 setName方法可以设置线程的名字。
9
main main thread public class mainthread {
public static void main(String[ ] args) { Thread thread = Thread.currentThread(); System.out.println(thread.getName()); thread.setName(“main thread”); System.out.println(thread.getName()); } main main thread
10
继承Thread类 常用构造方法:public Thread() public Thread(String name) public Thread(Runnable target) Thread thread1 = new Thread(); Thread thread2 = new Thread(“second”); class TestThread extends Thread{ public TestThread(String name){ super(name); } ………… TestThread thread1 = new TestThread(“second”);
11
调用该方法启动线程,使线程从新建状态转入就绪状态并进入就绪队列。 public void run()
Thread类的常用方法 public void start() 调用该方法启动线程,使线程从新建状态转入就绪状态并进入就绪队列。 public void run() Thread类中run()方法体为空,编写Thread类的子类时,需要在子类中覆盖父类的run()方法,该方法中包含了对线程的操作。 class mythread extends Thread { ………… public void run( ) { /* 覆盖该方法*/ }
12
需要注意的问题 程序需要建立自己的线程时,只需要创建一个已定义好的Thread子类的实例就行了。 当创建的线程调用start()方法开始运行时,run()方法将被自动执行。 当run()方法执行完毕,线程就释放内存。 在线程没有结束run()方法前,不赞成让线程再调用start()方法,否则将发生IllegalThreadStateException异常
13
public static void sleep(long millis)
优先级高的线程在它的run()方法中调用sleep方法来使自己放弃处理器资源,休眠一段时间。 public final boolean isAlive() 检查线程是否仍然在运行。 Static Thread currentThread() 判断当前正在占有CPU的线程。
14
public class LeftAndRight{ public static void main(String[] args){ Lefthand left;
Righthand right; left=new Lefthand();//创建线程 right=new Righthand(); left.start();//线程开始运行后,Lefthand类中run方法被执行 right.start(); //线程开始运行后,Righthand类中run方法被执行 } } 运行结果: ABBABBABAA class Lefthand extends Thread{ public void run(){ for(int i=1;i<=5;i++){ System.out.printl(“A”); try{ sleep(500); } catch(InterruptedException e){} } } } class Righthand extends Thread{ public void run(){ for(int i=1;i<=5;i++){ System.out.print(“B”); try{ sleep(300); } catch(InterruptedException e){} } } }
15
实现Runnable接口 Runnabale接口只有一个方法run(),所有实现Runnable接口的类都必须具体实现run()方法,定义具体操作。 class mythread implements Runnable{ public void run( ){ /* 实现该方法*/ } 一个实现了Runnable接口的类实际上定义了一个主线程外的新线程的操作。
16
public Thread(Runnable target) 使用Runnable对象创建一个线程对象。
public Thread(Runnable target,String name) 使用Runnable对象创建一个线程对象。 参数target称为被创建线程的目标对象,创建目标对象的类负责实现Runable接口。 class runnable implements Runnable{ public runnable(){ Thread thread = new Thread(this, "second"); } public void(){ …………
17
线程的基本控制 检查线程 挂起线程 使用isAlive()方法检查线程是否在活动状态。 活动状态说明这个线程已经被启动,并不一定正在执行。
使用sleep()来延迟线程的执行。 通常,线程不是休眠期满后就立即被唤醒(start),重新调度的情况是: 被唤醒的线程具有更高的优先级。 正在执行的线程因为其他原因被阻塞。 程序处于支持时间片的系统中。
18
结束线程 自然结束:从run()结尾返回 public void interrupt(),当线程阻塞时,会抛出InterruptedException异常,所以往往需要调用public void isInterrupted()方法来判断线程的阻塞状态 不推荐使用的方法 public final void stop() public final void suspend() public final void resume()
19
线程同步 对象的锁定标志 当两个或多个线程同时访问同一个对象,且其中一个线程要修改这个对象,这时可能产生混乱,这就是典型的同步问题。
Java可以为每一个对象的实例分配一个标志,称为锁定标志,用来处理同步问题。 每个线程通过排队等待的方式获得这个锁定标志来独享对象。 synchronized提供了操作这个标志的方法。 当持有锁定标志的线程运行完synchronized调用包含的语句后,这个标志会被自动返回
20
例:会计和出纳共同拥有一个账本,他俩都可以使用存取方法对账本进行访问,但不能同时对账本的账目进行访问
同步方法 synchronized() 标准写法:public void test(){ synchronized(this){ …… } } 简洁写法:public synchronized test(){ ……… } 例:会计和出纳共同拥有一个账本,他俩都可以使用存取方法对账本进行访问,但不能同时对账本的账目进行访问
21
使用wait()、notify()和notifyAll()进行线程间的交互
这种交互是通过队列来实现的。 wait()、notify()和notifyAll()都是Object类中的final方法,被所有的类继承,且不允许重写的方法。
22
public final void wait()
使用wait()方法可以中断方法的执行,使本线程等待,暂时让出CPU的使用权,并允许其他线程使用这个同步方法。
23
public final void notifyAll()
只是通知第一个处于等待状态的线程结束等待,并唤醒它。 例:模拟两个人排队买票,张某、李某买电影票,售票员只有两张5元的钱,电影票5元一张。张某拿一张20元排在李的前面,李某排拿一张5元买票。
24
线程联合 一个线程A在占有CPU资源期间,可以让其它线程和本线程联合。
如果线程A在占有CPU资源期间一旦联合B线程,那么A线程将立刻中断执行,一直等到它联合的线程B执行完毕,A线程再重新排队等待CPU资源,以便恢复执行。
25
线程的联合使用方法join()实现 public final void join() 直到调用该方法的线程结束。 public final void join(long timeout) 挂起timeout毫秒,或直到线程结束,实际以二者中较少者为准 上述两个方法将抛出InterruptedException在程序中应予以捕捉
Similar presentations