Java第九章多线程程序设计基础篇.ppt_第1页
Java第九章多线程程序设计基础篇.ppt_第2页
Java第九章多线程程序设计基础篇.ppt_第3页
Java第九章多线程程序设计基础篇.ppt_第4页
Java第九章多线程程序设计基础篇.ppt_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第九章 多线程程序设计,9.1 线程的概念 9.2 Java 线程的创建 9.3 线程状态和线程控制 9.4 线程优先级和线程的调度 9.5 线程同步 9.6 线程的死锁,9.1 线程的概念,进程:一个执行中的程序,有自己独立的内存空间等系统资源。 线程:程序中单个顺序的流控制,单个程序中多个线程共享系统资源。 多线程编程:将任务分成多个并发的子任务。 Java支持多线程。,9.2 Java 线程的创建,继承Thread类的方法 实现Runnable接口的方法 线程体 有run方法(一般是一个循环,需 要以线程方式运行的代码),1 继承Thread类的方法,通过实现Thread类的子类、并置换

2、其中的run()方法定义线程体,然后创建该子类的对象创建线程。如: public class Counter extends Thread public void run() /定义线程的行为 启动线程 Counter threadCounter = new Counter(); threadCounter.start();,2 实现Runnable接口的方法,通过在类中实现Runnable接口,并在该类中提供run()方法的实现。如: public class Counter implements Runnable public void run() /定义线程的行为 启动线程 Counte

3、r C1 = new Counter(); new Thread(C1).start(); Counter C1 = new Counter(); Thread t1 = new Thread(C1); t1.start();,3 Thread类构造器和Threadgroup类,Thread 类构造器: Thread() Thread(Runnable) Thread(Threadgroup,Runnable) Thread(String) Thread(Threadgroup,String) Thread(Runnable,String) Thread(Threadgroup,Runnabl

4、e,String) Runnable:类的实例,调用Run()方法的对象 Threadgroup:新创建的线程所属的线程组 String:表示新线程的名字,3 Thread类构造器和Threadgroup类,Threadgroup 类(线程组):所有的线程一定属于某个线程组。属于Java.lang包。用于进行统一管理。 显式:ThreadGroup myThreadGroup = new ThreadGroup(“my group of threads”) 隐式:新创建的线程自动的属于创建该线程的线程所在的线程组。,例 线程概念例子,class PrintThread extends Thre

5、ad private int sleepTime; public PrintThread( String name ) super( name ); sleepTime = (int) ( Math.random() * 5000 ); System.out.println( Name: + getName() + ; sleep: + sleepTime ); ,例 线程概念例子,public void run() try System.out.println( getName() + going to sleep ); Thread.sleep( sleepTime ); catch (

6、InterruptedException exception ) System.err.println( exception.toString() ); System.out.println( getName() + done sleeping ); ,例 线程概念例子,public class PrintThreadTest public static void main( String args ) PrintThread thread1 = new PrintThread( thread1 ); PrintThread thread2 = new PrintThread( thread2

7、 ); PrintThread thread3 = new PrintThread( thread3 ); PrintThread thread4 = new PrintThread( thread4 ); System.out.println( nStarting threads ); thread1.start(); thread2.start(); thread3.start(); thread4.start(); System.out.println( Threads startedn ); ,9.3 线程状态和线程控制,类Thread的常用方法 控制和状态的关系 例子,线程状态,1

8、类Thread的常用方法,1 类Thread的常用方法,1 类Thread的常用方法,2 控制和状态的关系,创建,可运行,运行中,死亡,其它 阻塞,互斥阻塞,等待阻塞,Start(),调度时间到,运行结束,Yield(),Wait(),Notify() Interrupt(),Synchronized,Sleep() Join(),线程结束 或时间到 或interupt(),获得互斥使用权,不可运行,3 例子时钟,import java.awt.Graphics; import java.util.*; import java.applet.Applet ; public class Cloc

9、k extends Applet implements Runnable Thread clockThread; public void start() if(clockThread = null) clockThread = new Thread(this,Clock); clockThread.start(); public void run() while(clockThread!=null) repaint();,3 例子时钟,try clockThread.sleep(1000); catch(InterruptedException e) public void paint(Gra

10、phics g) Calendar now = new GregorianCalendar(); Date trialTime = new Date(); now.setTime(trialTime); g.drawString(now.get(Calendar.HOUR_OF_DAY)+: +now.get(Calendar.MINUTE)+:+now.get(Calendar.SECOND),5,10); public void stop() clockThread = null; ,3 例子时钟, ,9.4 线程优先级和线程的调度,线程的调度取决于线程的优先级。采用先占式调度,先占调度有

11、分为: 独占方式 分时方式 线程的优先级可以用setPriority()显式进行设置。getPriority()获得优先级。 线程优先级用整数表示。从1到10,Thread.MIN_PRIORITY(1), Thread.MAX_PRIORITY(10), Thread.NORM_PRIORITY(5) 例,9.4 线程优先级和线程的调度画线,import java.applet.Applet; import java.awt.Color; public class RaceApplet extends Applet implements Runnable final static int N

12、UMRUNNERS = 2; final static int SPACING = 20; Runner runners = new RunnerNUMRUNNERS; Thread updateThread = new Thread(this,control); public void init()for(int i=0;iNUMRUNNERS;i+) runnersi = new Runner(); runnersi.setPriority(i+1); public boolean mouseDown(java.awt.Event evt,int x,int y),9.4 线程优先级和线程

13、的调度,if(!updateThread.isAlive() updateThread.start(); for(int i=0;iNUMRUNNERS;i+) if(!runnersi.isAlive() runnersi.start(); return true; public void paint(java.awt.Graphics g) g.setColor(Color.lightGray); g.fillRect(0,0,400,500); g.setColor(Color.black); for(int i=0;iNUMRUNNERS;i+) int pri = runnersi.

14、getPriority(); g.drawString(new Integer(pri).toString(),0,(i+1)*SPACING); update(g);,9.4 线程优先级和线程的调度,public void update(java.awt.Graphics g ) for(int i=0;iNUMRUNNERS;i+) g.drawLine(SPACING,(i+1)*SPACING,SPACING+(runnersi.tick)/1000,(i+1)*SPACING); public void run() while(updateThread!=null) repaint(

15、); try updateThread.sleep(100); catch(InterruptedException e) ,9.4 线程优先级和线程的调度,public void stop() for(int i=0;iNUMRUNNERS;i+) if(runnersi.isAlive()runnersi = null; if(updateThread.isAlive() updateThread = null; Class Runner extends Thread public int tick = 1; public void run() while(tick400000) tick

16、+; ,9.5 线程同步- 数据的完整性,因多线程并发而引起执行顺序的不确定性,执行的不确定性会产生执行结果的不确定性。在多个线程需要共享数据时通常会产生这种不确定性。对共享对象的访问必须同步,叫做条件变量. Java语言允许通过监视器(有的参考书称其为管程)使用条件变量实现线程同步. 监视器阻止两个线程同时访问同一个条件变量.它如同锁一样作用在数据上. 线程1进入withdrawal方法时,获得监视器(加锁);当线程1的方法执行完毕返回时,释放监视器(开锁),线程2的withdrawal方能进入.,9.5 线程同步- 数据的完整性,用synchronized来标识的区域或方法即为监视器监视的

17、部分。 一个类或一个对象有一个监视器,如果一个程序内有两个方法使用synchronized标志,则他们在一个监视器管理之下. 一般情况下,只在方法的层次上使用关键区,9.5 线程同步- 数据的完整性,此处给出的例子演示两个线程在同步限制下工作的情况. class Account static int balance=1000; /为什么用static? static int expense=0; public synchronized void withdrawl(int amount) if (amount=balance) balance-=amount; expense+=amount;

18、 else System.out.println(“bounced: “+amount); ,9.5 线程同步-等待同步数据,可能出现的问题: 生产者比消费者快时,消费者会漏掉一些数据没有取到 消费者比生产者快时,消费者取相同的数据. notify()和wait ()方法用来协调读取的关系. notify()和wait ()都只能从同步方法中的调用.,9.5 线程同步-等待同步数据,notify的作用是唤醒正在等待同一个监视器的线程. wait的作用是让当前线程等待 read()方法在读信息之前先等待,直到信息可读,读完后通知要写的线程. write()方法在写信息之前先等待,直到信息被取走,

19、写完后通知要读的进程.,例 生产者/消费者例子(有同步),/ HoldIntegerSynchronized.java public class HoldIntegerSynchronized private int sharedInt = -1; private boolean writeable = true; / condition variable public synchronized void setSharedInt( int val ) while ( !writeable ) / not the producers turn try wait(); catch ( Inter

20、ruptedException e ) e.printStackTrace(); System.err.println( Thread.currentThread().getName() + setting sharedInt to + val );,sharedInt = val; writeable = false; notify(); / tell a waiting thread to become ready public synchronized int getSharedInt() while ( writeable ) / not the consumers turn try

21、wait(); catch ( InterruptedException e ) e.printStackTrace(); writeable = true; notify(); / tell a waiting thread to become ready,System.err.println( Thread.currentThread().getName() + retrieving sharedInt value + sharedInt ); return sharedInt; / ProduceInteger.java public class ProduceInteger exten

22、ds Thread private HoldIntegerSynchronized pHold; public ProduceInteger( HoldIntegerSynchronized h ) super( ProduceInteger ); pHold = h; public void run() for ( int count = 1; count = 10; count+ ) pHold.setSharedInt( count ); ,System.err.println( getName() + finished producing values + nTerminating +

23、 getName() ); / ConsumeInteger.java public class ConsumeInteger extends Thread private HoldIntegerSynchronized cHold; public ConsumeInteger( HoldIntegerSynchronized h ) super( ConsumeInteger ); cHold = h; public void run() int val, sum = 0; do val = cHold.getSharedInt(); sum += val;, while ( val !=

24、10 ); System.err.println(getName() + retrieved values totaling: + sum + nTerminating + getName() ); / SharedCell.java public class SharedCell public static void main( String args ) HoldIntegerSynchronized h = new HoldIntegerSynchronized(); ProduceInteger p = new ProduceInteger( h ); ConsumeInteger c

25、 = new ConsumeInteger( h ); p.start(); c.start(); ,9.6 线程的死锁,死锁:指两个或多个线程无止境地相互等待的过程。错误的同步往往会引起死锁。 程序员认真设计避免死锁。如果你持有一个锁并试图获取另一个锁时,就有死锁的危险. 解决死锁问题的方法:对共享资源访问的顺序,即给条件变量施加排序。,9.7 多线程问题-线程间的通信,1. 线程间的通信可以用管道流 创建管道流: PipedInputStream pis=new PipedInputStream(); PipedOutputStream pos=new PipedOutputStream(

26、pis); 或: PipedOutputStream pos=new PipedOutputStream(); PipedInputStream pis=new PipedInputStream(pos);,9.7 多线程问题-线程间的通信,管道流不能直 接读写 PrintStream p = new PrintStream( pos ); p.println(“hello”); DataInputStream d=new DataInputStream(pis); d.readLine(); 管道流可以连接两个线程间的通信 将一个写线程的输出通过管道流定义为读线程的输入.,9.7多线程问题-

27、线程间的通信,主类Pipethread,辅类Writer 线 程 类,辅类 Reader 线 程 类,管 道 流,将数据写 到输出流,从流中读数据,输入流,作为参数传给Writer Writer( outStream ),7.4 多线程问题-线程间的通信,.,public class Pipethread public static void main(String args) Pipethread thisPipe = new Pipethread(); thisPcess(); public void process() PipedInputStream inStream;

28、PipedOutputStream outStream; PrintStream printOut; try outStream = new PipedOutputStream(); inStream = new PipedInputStream(outStream); new Writer( outStream ).start(); new Reader( inStream ).start(); catch( IOException e ) ,7.4 多线程问题-线程间的通信,class Reader extends Thread private PipedInputStream inStr

29、eam;/从中读数据 public Reader(PipedInputStream i) inStream = i; public void run() String line; DataInputStream d; boolean reading = true; try d = new DataInputStream( inStream ); while( reading catch( InterruptedException e ),7.4 多线程问题-线程间的通信,.,class Writer extends Thread private PipedOutputStream outStr

30、eam;/将数据输出 private String messages = Monday, Tuesday , Wednsday,Thursday,Friday :, Saturday:,Sunday :; public Writer(PipedOutputStream o) outStream = o; public void run() PrintStream p = new PrintStream( outStream ); for (int i = 0; i messages.length; i+) p.println(messages i ); p.flush(); System.ou

31、t.println(WrIte: + messagesi ); p.close(); p = null; ,小结,线程概念 线程状态及线程控制 线程优先级和线程调度 线程同步 线程通信 读写程序,习题,什么是线程?线程和进程的区别。 创建线程有哪些方法,如何使用? 线程有哪几种状态?是如何进行控制的? 请编写一个程序,实现在一分钟后显示当时的时间。 当我们编译下面的代码时,会发生什么情况?,习题,Public class Runt implements Runnable public static void main(String args) Runt r1 = new Runt(); Thr

32、ead t = new Thread(r1); t.start(); public void start() for(int i = 0;i100;i+) System.out.println(i); ,习题,创建两个线程的实例,分别将一个数组从小到大和从大到小排列.输出结果. 当我们编译运行下面的代码时,会发生什么情况? Public class TGo implements Runnable public static void main(String args) TGo r1 = new TGo(); Thread t = new Thread(r1); t.start(); public void run() while(true) Thread.currentThread().sleep(1000); System.out.println( looping while ); ,public class ThreadTest public static void main( String args ) int a = 2, 6, 4, 8, 10, 12, 89, 68, 45

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论