多线程课件.ppt

上传人:牧羊曲112 文档编号:1572814 上传时间:2022-12-07 格式:PPT 页数:66 大小:918KB
返回 下载 相关 举报
多线程课件.ppt_第1页
第1页 / 共66页
多线程课件.ppt_第2页
第2页 / 共66页
多线程课件.ppt_第3页
第3页 / 共66页
多线程课件.ppt_第4页
第4页 / 共66页
多线程课件.ppt_第5页
第5页 / 共66页
点击查看更多>>
资源描述

《多线程课件.ppt》由会员分享,可在线阅读,更多相关《多线程课件.ppt(66页珍藏版)》请在三一办公上搜索。

1、7. Java 多线程,1,内容,多线程基本概念Java多线程创建多线程线程的状态控制Java多线程的一些问题小结注: 本课件部分材料来自网络,2,1 多线程基本概念,文件,输入输出装置,各种系统资源,数据区段,程序区段,只有一个地方在执行,文件,输入输出装置,各种系统资源,程序区段,同时有数个地方在执行,传统的进程,多线程的任务,3,多线程的优势:减轻编写交互频繁、涉及面多的程序的困难程序的吞吐量会得到改善由多个处理器的系统,可以并行运行不同的线程(否则,任何时刻只有一个线程在运行,形成并发运行),4,线程与进程的区别:多个进程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和一组

2、系统资源,有可能互相影响线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要小,5,多线程编程原则,安全性: 如果两个以上的线程访问同一对象时,一个线程会损坏另一个线程的数据,这就违反了安全性原则可行性: 如果仅仅实现了安全性,程序却在某一点后不能继续执行或者多个线程发生死锁,那么这样的程序也不能作为真正的多线程程序来应用高性能:多线程的目的是为了增加程序运行的性能,6,2. Java线程概念,对线程的综合支持是Java技术的一个重要特色.它提供了thread类、监视器和条件变量的技术.虽然许多操作系统支持多线程,但若要用C或C+编写多线程程序是十分

3、困难的,因为它们对数据同步的支持不充分.,7,线程对象和线程的区别:线程对象是可以产生线程的对象比如在java平台中Thread对象,Runnable对象。线程,是指正在执行的一个指令序列。在java平台上是指从一个线程对象的start()开始,运行run方法体中的那一段相对独立的过程。,8,思考如果我们成功编译了该java文件,然后运行发生的过程Jvm进程启动, JVM产生一个主线程还有一些其它线程,例如垃圾回收等,class BeginClass public static void main(String args) for(int i=0;i100;i+) System.out.pri

4、ntln(Hello,World!); ,9,剖析多线程程序,class MyThread extends Thread public void run() System.out.println(Thread say:Hello,World!); public class MoreThreads public static void main(String args) new MyThread(); new MyThread().start(); System.out.println(Main say:Hello,World); ,10,3. 创建多线程,Runnable 与Thread1.

5、public class mythread extends Applet implements Runnable (小应用或已经是某个类的子类时)2. 继承类Thread public class mythread extends Thread创建方法:newthread=new Thread(this);newthread.start();,11,Runable与Thread的区别使用runable最主要的原因是:java缺少多重继承的机制,可能你的类已经继承了其他类了,这时你无法继承自thread类,只能用runnable了Runable 创建的线程共享数据区,12,ublic class

6、 Test public static void main(String args) throws Exception MyThread mt = new MyThread(); mt.start(); mt.join(); Thread.sleep(3000); mt.start(); 输出:Exceptioninthreadmainjava.lang.IllegalThreadStateException说明:通过Thread实例的start(),一个Thread的实例只能产生一个线程,13,class R implements Runnable private int x = 0; pu

7、blic void run() for(int i=0;i100;i+) try Thread.sleep(10); catch(Exception e) System.out.println(x+); ,public class Test public static void main(String args) throws Exception R r = new R(); for(int i=0;i10;i+) new Thread(r).start(); ,14,package debug; import java.io.*; import java.lang.Thread; class

8、 MyThread extends Thread public int x = 0; public void run() System.out.println(+x); class R implements Runnable private int x = 0; public void run() System.out.println(+x); ,ublic class Test public static void main(String args) throws Exception for(int i=0;i10;i+) Thread t = new MyThread(); t.start

9、(); Thread.sleep(10000);/让上面的线程运行完成 R r = new R(); for(int i=0;i10;i+) Thread t = new Thread(r); t.start(); ,15,重要的方法,start()从CPU中申请另一个线程空间来执行run()方法中的代码run()是运行线程的主体,启动线程时,由java直接调用 public void run() 如果你不调用Start, 直接调用run, 会如何?stop()停止线程, 调用线程的 newthread.stop() (不是安全的处理) sleep方法暂停线程的执行,让其它线程得到机会,sle

10、ep要丢出异常,必须抓住: Trysleep(100)catch(InterruptedException e),16,import javax.swing.*;public class Applet1 extends JAppletmythread t1=new mythread(); public void init() t1.start();class mythread extends Thread public void run() for (int i=0;i4;i+) System.out.println( +i); try sleep(400); catch(Interrupte

11、dException e) ,17,7.2 创建线程的方式,import javax.swing.*;import java.awt.*;public class Applet1 extends JApplet C t1=new C(this); public void init() t1.start(); public void paint(Graphics g) g.drawString(Hello,java,10,50); class C extends Thread Applet1 a; C(Applet1 b) a=b; public void run() while(true) a

12、.repaint();try sleep(400); catch(InterruptedException e) ,18,join:等待线程执行完毕,被等待的那个线程不结束,当前线程就一直等待.,public class Test public static void main(String args) throws Exception MyThread mt = new MyThread(); mt.start(); mt.join(); System.out.println(101); ,19,其它常用的方法 isAlive :判断线程目前是否正在执行状态中 if(newthread.is

13、Alive() newthread.stop(); resume:要求被暂停线程继续执行 suspend:暂停线程的执行 yield:将执行的权力交给其它线程,自己到队列的最后等待.,20,线程的优先权某一时刻只有一个线程在执行,调度策略为固定优先级调度.newthread.setPriority(Thread.MIN_PRIORITY)级别有:MIN-PRIORITY NOM_PRIORITY MAX-PRIORITY自私的线程:有很高的优先权的线程,不主动睡眠或让出处理器控制权.,21,4. 线程的状态控制,线程的状态,22,当一个线程执行完所有语句后就自动终止调用线程的stop()方法,

14、也可以强制终止线程,可能产生不完整的残废数据 。如果希望线程正常终止,可采用标记来使线程中的run()方法退出,23,public class Xyz implements Runnable private boolean timeToQuit=false; public void run() while (!timeToQuit) . /clean up before run() ends; public void stopRunning() timeToQuit=true;,24,public class ControlThread private Runnable r=new Xyz()

15、; private Thread t=new Thread(r); public void startThread() t.start(); publi void stopThread() r.stopRunning();,25,暂停线程的执行等待条件满足再执行下面的例子显示线程的挂起和唤醒Applet第一次开始时,线程被启动浏览器改变页面时,小应用程序的stop()方法被调用,线程被挂起.浏览器回到原来的页面时,线程被唤醒.,26,public void start() if (mythread=null) mythread=new Thread(); mythread.start(); e

16、lse mythread.resume();public void run() while(true) trysleep(100); catch(InterruptedException e) public void stop()mythread.suspend();.,27,5 . Java多线程问题,执行顺序多个线程运行时,调度策略为固定优先级调度.级别相同时,由操作系统按时间片来分配下面给出的例子中,共运行三个线程,它们做同样的事, 每次打印循环次数和自己的序列号,运行结果表明,它们并不是连续运行的.如果给某个线程赋予较高的优先权,则发现这个进程垄断控制权 thread.setPrior

17、ity(Thread.MAX_PRIORITY),28,7.3 多线程问题,/多个进程运行时执行顺序是交叉的public class MyThread extends Thread int threadNum; public static void main(String args) MyThread array=new MyThread3; for (int i=0;i ); trysleep(1000);catch(InterruptedException e); System.out.println(thread +threadNum+ bye.);,29,如何写多线程,1.分别定义不同

18、的线程类,在各自的run方法中定义线程的工作 class mythread1 extends Thread public void run. class mythread2 extends Thread public void run. 2. 在主类中实例化各线程类,并启动线程. public class demo extends Applet public void init() mythread t1=new mythread1(); mythread t2=new mythread2(); t1.start(); t2.start(); ,30,练习:将窗口分为上下两个区,分别运行两个线

19、程,一个在上面的区域中显示由右向左游动的字符串,另一个在下面的区域从左向右游动的字符串.方法一: 一个线程,在paint方法中使用两个输出字符串的语句public void paint(Graphics g) if y1200 y2=0 else y2=y2+10; g.drawString(“hello, Java!”,20,y1,); g.drawString(“hello, Java!”,40,y2,);,31,方法二:定义两个类,运行各自的线程,各自有自己的paint()方法.注意: 两个Applet必须是panel类或者是canvas类,将Applet的区域分成两块,否则不能运行pa

20、int语句.,32,import javax.swing.*;import java.awt.*;public class Applet1 extends JApplet C t1,t2; myCanvas c1,c2; Container contentPane = getContentPane( ); public void init() c1=new myCanvas(); c2=new myCanvas(); contentPane.setLayout(new GridLayout(2,1); contentPane.validate(); contentPane.add(c1); c

21、ontentPane.add(c2); t1=new C(c1,5); t2=new C(c2,-5); t1.start(); t2.start(); ,class myCanvas extends Canvaspublic void paint(Graphics g, int x,int y)g.drawString(Hello World, x, y); class C extends Thread myCanvas a; int steps; int x; C(myCanvas b,int size) a=b; steps=size; x=0;public void run() whi

22、le(true) x=x+steps;if (xa.getWidth() x=0;a.repaint();a.paint(a.getGraphics(),x,50);try sleep(10); catch(InterruptedException e) ,33,线程间的通信,1. 线程间的通信可以用管道流,.创建管道流:PipedInputStream pis=new PipedInputStream();PipedOutputStream pos=new PipedOutputStream(pis);或:PipedOutputStream pos=new PipedOutputStream

23、();PipedInputStream pis=new PipedInputStream(pos);,34,管道流不能直 接读写PrintStream p = new PrintStream( pos );p.println(“hello”);DataInputStream d=new DataInputStream(pis);d.readLine();2. 通过一个中间类来传递信息.,35,管道流可以连接两个线程间的通信两个线程在运行,一个往外输出信息,一个读入信息.将一个写线程的输出通过管道流定义为读线程的输入.outStream = new PipedOutputStream();inS

24、tream = new PipedInputStream(outStream);new Writer( outStream ).start();new Reader( inStream ).start();,36,主类Pipethread,辅类Writer线程类,辅类Reader线程类,管道流,将数据写到输出流,从流中读数据,输入流,作为参数传给WriterWriter( outStream ),37,7.4 多线程问题-线程间的通信,.,import java.io.*;public class Pipethread public static void main(String args)

25、Pipethread thisPipe = new Pipethread(); thisPipe.process(); public void process() PipedInputStream inStream; PipedOutputStream outStream; PrintStream printOut; try outStream = new PipedOutputStream(); inStream = new PipedInputStream(outStream); new Writer( outStream ).start() new Reader( inStream ).

26、start(); catch( IOException e ) ,38,7.4 多线程问题-线程间的通信,class Reader extends Thread private PipedInputStream inStream; public Reader(PipedInputStream i)inStream=i; public void run() String line; DataInputStream d; boolean reading = true; d = new DataInputStream( inStream ); while(reading ,39,7.4 多线程问题-

27、线程间的通信,.,class Writer extends Thread private PipedOutputStream outStream; 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 message

28、s.length;i+) p.println(messagesi); p.flush(); System.out.println(WrIte: + messagesi ); try Thread.sleep(4000); catch(InterruptedException e); p.close(); p = null; ,40,结果可能是:,WrIte:MondayRead: MondayWrIte:TuesdayRead: TuesdayRead: WednsdayWrIte:WednsdayRead: ThursdayWrIte:ThursdayRead: Friday :WrIte:

29、Friday :WrIte:Saturday:Read: Saturday:Read: Sunday :WrIte:Sunday :,41,资源协调,42,资源协调,43,对共享对象的访问必须同步,叫做条件变量.Java语言允许通过监视器(有的参考书称其为管程)使用条件变量实现线程同步.监视器阻止两个线程同时访问同一个条件变量.它如同锁一样作用在数据上.线程1进入withdrawal方法时,获得监视器(加锁);当线程1的方法执行完毕返回时,释放监视器(开锁),线程2的withdrawal方能进入.,44,用synchronized来标识的区域或方法即为监视器监视的部分。一个类或一个对象有一个监

30、视器,如果一个程序内有两个方法使用synchronized标志,则他们在一个监视器管理之下.一般情况下,只在方法的层次上使用关键区,45,此处给出的例子演示两个线程在同步限制下工作的情况.class Account statics int balance=1000; statics int expense=0; public synchronized void withdrawl(int amount) if (amount=balance) balance-=amount; expense+=amount; else System.out.println(“bounced: “+amount

31、); ,46,实例范围同步方法 publicd class syncTest synchronized void aMethod() /需要同步使用的代码 synchronized aMethod()可以防止多个线程同时访问这个对象实例的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。,47,实例范围同步区块 publicd class syncTest void aMethod() /无需同步使用的代码 synchronized(thi

32、s) /需要同步使用的代码块 除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this)/*区块*/,它的作用域是当前对象。,48,类范围 在类范围内使用synchronized也有同步方法和同步区块两种形式: 类范围同步方法 publicd class syncTest synchronized static void aMethod() /需要在类范围同步使用的代码 ,49,synchronized static aStaticMethod防止多个线程同时访问这个

33、类中的synchronized static 方法。它可以对类的所有对象实例起作用。也就是说在一个JVM中,同一时间最多有一个该类的静态同步方法在执行。这样的方法可以应用到多线程的同步中,实现各线程直接的数据共享和互动,50,类范围同步区块 publicd class syncTest static void aMethod() /无需同步使用的代码 synchronized (syncTest.class) /需要在类范围同步使用的代码 类范围同步区块功能与类范围同步方法相同,只是对一个区块的代码的同步。用法是:在static 方法内加同步区块:sychronized (类名.class)

34、/*区块*/。,51,synchronized关键字是不能继承的,也就是说,基类的方法synchronized f() 在继承类中并不自动是synchronized f(),而是变成了f()。继承类需要你显式的指定它的某个方法为synchronized方法;,52,2. 等待同步数据,可能出现的问题:生产者比消费者快时,消费者会漏掉一些数据没有取到消费者比生产者快时,消费者取相同的数据.notify()和wait ()方法用来协调读取的关系.notify()和wait ()都只能从同步方法中的调用.,53,notify的作用是唤醒正在等待同一个监视器的线程.wait的作用是让当前线程等待信息版

35、例子read()方法在读信息之前先等待,直到信息可读,读完后通知要写的线程.write()方法在写信息之前先等待,直到信息被取走,写完后通知要读的进程.,54,writer,reader,aaaa,bbbbb,cccc,aaaa,aaaa,aaaa,aaaa,aaaa,aaaa,bbbbb,cccc,cccc,cccc,cccc,bbbbb,cccc,55,public class WaitNotifyDemo public static void main(String args) MessageBoard m = new MessageBoard(); Reader readfrom_m

36、= new Reader(m); Writer writeto_m=new Writer(m); writeto_m.start(); readfrom_m.start(); ,56,7.3 多线程问题-资源协调,class MessageBoard private String message; private boolean ready = false; public synchronized String read() while (ready = false) try wait(); catch (InterruptedException e) ready = false; notif

37、y(); return message; public synchronized void write(String s) while (ready = true) try wait(); catch (InterruptedException e) message = s;System.out.println(Boad Got:+s); ready = true; notify(); ,57,7.3 多线程问题-资源协调,class Reader extends Thread private MessageBoard mBoard; public Reader(MessageBoard m)

38、 mBoard = m; public void run() String s = ;boolean reading = true;while( reading ) s = mBoard.read(); System.out.println(Reader read: + s); if( s.equals(logoff) ) reading = false; System.out.println(Finished: 10 seconds.); try sleep( 10000 ); catch (InterruptedException e) ,58,7.3 多线程问题-资源协调,class W

39、riter extends Thread private MessageBoard mBoard; private String messages = Monday :-,.,Sunday : -; public Writer(MessageBoard m) mBoard = m; public void run() for (int i = 0; i messages.length; i+) System.out.println(Writer wrote: + messagesi ); mBoard.write(messages i ); try sleep(int)(Math.random

40、() * 100); catch (InterruptedException e) System.out.println(Writer wrote: + logoff); mBoard.write(logoff); ,59,notifyAll()让等待某个对象K的所有线程离开阻塞状态, notify()随机地选取等待某个对象K的线程,让它离开阻塞状态sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非:(a)“醒来”的线程具有更高的优先级 (b)正在运行的线程因为其它原因而阻塞

41、,60,waite()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronizedblock中进行调用。如果在non-synchronized函数或non-synchronizedblock中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常,61,多线程问题-资源的协调和锁定1. 死锁问题如果你持有一个锁并试图获取另一个锁时,就有死锁的危险.解决死锁问题的方法:给条件变量施加排序,62,多线程问题-daemon线程,什么是daemon(守护)?在客户/服务器模式下,服务器的作用是

42、等待用户发来请求,并按请求完成客户的工作守护线程是为其它线程提供服务的线程守护线程一般应该是一个独立的线程,它的run()方法是一个无限循环.守护线程与其它线程的区别是,如果守护线程是唯一运行着的线程,程序会自动退出,客户端,服务器端,request,daemon,63,调用isDaemon(),可调查一个线程是不是一个DaemonsetDaemon()打开或者关闭一个线程的Daemon状态如果是一个Daemon线程,那么它创建的任何线程也会自动具备Daemon属性。,64,小结,1. 实现线程有两种方法:实现Ruannable接口继承Thread类2. 在小应用中通常在start中创建线程3.当新线程被启动时,java调用该线程的run方法,它是Thread的核心.4. 线程由四个状态:新生,运行,暂停,死亡,65,5. 两个或多个线程竞争资源时,需要用同步的方法协调资源.6. 多个线程执行时,要用到同步方法,即使用 synchronized的关键字设定同步区7. wait和notify起协调作用8. 守护进程的特点是当程序中只剩它自己时,会自动中止.,66,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号