首页 多线程程序设计

多线程程序设计

举报
开通vip

多线程程序设计nulljava多线程程序设计java多线程程序设计shenxueping@buaa.edu.cn主要知识点主要知识点线程的概念 线程的调度 创建和启动线程 Thread线程类、 Runnable接口 多个线程的同步 线程之间的通信多线程多线程程序:是一段静态的代码,它是应用程序执行的蓝本。 进程:是程序的一次动态执行过程,它对应了从代码加载、执行到执行完毕的一个完整过程,也是进程本身从产生、发展至消亡的过程。 目前所流行的操作系统中,大部分都是支持多任务的(如Windows 3.X,Windows NT,Wind...

多线程程序设计
nulljava多线程程序 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 java多线程程序设计shenxueping@buaa.edu.cn主要 知识点 高中化学知识点免费下载体育概论知识点下载名人传知识点免费下载线性代数知识点汇总下载高中化学知识点免费下载 主要知识点线程的概念 线程的调度 创建和启动线程 Thread线程类、 Runnable接口 多个线程的同步 线程之间的通信多线程多线程程序:是一段静态的代码,它是应用程序执行的蓝本。 进程:是程序的一次动态执行过程,它对应了从代码加载、执行到执行完毕的一个完整过程,也是进程本身从产生、发展至消亡的过程。 目前所流行的操作系统中,大部分都是支持多任务的(如Windows 3.X,Windows NT,Windows 95,OS/2及UNIX的各个版本),这实际就是一种多进程的概念——每一个任务就是一个进程。 线程:比进程更小的执行单位。一个进程在执行过程中,为了同时完成多项操作,可以产生多个线程,形成多条执行线索。每个线程都有它自身的产生、存在和消亡的过程。 线程和进程之间的关系:线程和进程之间的关系:多进程环境中每一个进程既包括其所要执行的指令, 也包括执行指令所需的任何系统资源, 如CPU、内存空间、I/O端口等,不同进程所占用的系统资源相对独立; 线程是比进程单位更小的执行单位,多线程环境中每一个线程都隶属于某一进程,由进程触发执行,在系统资源的使用上,属于同一进程的所有线程共享该进程的系统资源; 与进程不同的是线程本身即没有入口,也没有出口,其自身也不能独立运行,它栖身于某个进程之中,由进程启动运行,完成其任务后,自动终止,也可以由进程使之强制终止。 多线程程序设计:多线程程序设计:是指单个程序包含并发执行的多个线程。当多线程程序执行时,该程序对应的进程中就有多个控制流在同时执行,即具有并发执行的多个线程; 例如: PV操作 Web Server接受客户端的请求问题 银行问题 网络聊天(一对多)程序null一个多线程的例子:Test.java 此程序创建两个线程,分别执行存取款操作,并规定 每次存款25000元,每次取款50000元。null进程、线程示意图 为什么要使用多线程?为什么要使用多线程?由于线程在程序内部,多个线程共享一些系统的开销,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈。 例如线程之间共享相同的内存单元(代码和数据),因此在线程间切换,不需要很大的系统开销,所以线程之间的切换速度远远比进程之间快,线程之间的通信也比进程通信快的多。 多个线程轮流抢占CPU资源而运行时,从微观上讲,一个时间里只能有一个作业被执行,在宏观上可使多个作业被同时执行,即等同于要让多台计算机同时工作,使系统资源特别是CPU的利用率得到提高,从而可以提高整个程序的执行效率。线程运行环境线程运行环境null每一个进程就是一个应用程序。有自己的入口和出口。 多进程环境中每一个进程既包括其所要执行的指令, 也包括了执行指令所需的任何系统资源, 如CPU、内存空间、I/O端口等; 不同进程所占用的系统资源相对独立。多个线程可共同存在于一个应用程序中。 多线程环境中每一个线程都隶属于某一进程,由进程触发执行(没有自己的入口和出口); 在系统资源的使用上,属于同一进程的所有线程共享该进程的系统资源。线程之间切换的速度比进程切换要快得多。进程和线程的比较( 总结 初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf )线程的调度(1)线程的调度(1)微观上,在一台只具有一个CPU的机器上,CPU在同一时间只能分配给一个线程做一件事。 当有多于一个的线程工作时,在Java中,线程调度通常是抢占式(即哪一个线程先抢到CPU资源则先运行),而不是分时间片式。 一旦一个线程获得执行权,这个线程将持续运行下去,直到它运行结束或因为某种原因而阻塞,或者有另一个高优先级线程就绪(这种情况称为低优先级线程被高优先级线程所抢占)。线程的调度(2)线程的调度(2)所有被阻塞的线程按次序排列,组成一个阻塞队列。例如: 因为需要等待一个较慢的外部设备,例如磁盘或用户。 让处于运行状态的线程调用Thread.sleep()方法。 让处于运行状态的线程调用另一个线程的join()方法。 所有就绪但没有运行的线程则根据其优先级排入一个就绪队列。 当CPU空闲时,如果就绪队列不空,就绪队列中第一个具有最高优先级的线程将运行。 当一个线程被抢占而停止运行时,它的运行态被改变并放到就绪队列的队尾; 一个被阻塞(可能因为睡眠或等待I/O设备)的线程就绪后通常也放到就绪队列的队尾。 线程的调度与优先级线程的调度与优先级线程的调度是按: 其优先级的高低顺序执行的; 同样优先级的线程遵循“先到先执行的原则”; 线程优先级:范围 1~10 (10 级)。数值越大,级别越高 Thread 类定义的 3 个常数: MIN_PRIORITY 最低(小)优先级(值为1) MAX_PRIORITY 最高(大)优先级(值为10) NORM_PRIORITY 默认优先级(值为5) 线程创建时,继承父线程的优先级。 常用方法: getPriority( ):获得线程的优先级 setPriority( ):设置线程的优先级 ThreadPri.javanull主线程主线程主线程: main( ) 方法——Application 应用程序 每当用java命令启动一个Java虚拟机进程( Application 应用程序),Java虚拟机就会创建一个主线程,该线程从程序入口main()方法开始执行。 浏览器中加载的 Applet 主类——Applet 小程序 多线程:在主线程中创建 Thread 类或其子类对象时,就创建了一个线程对象。Programmer可以控制线程的启动、挂起与终止。nullpublic class Sample{ public void method1(String str){ System.out.println(str); } public void method2(String str){ method1(str); } public static void main(String args[]){ Sample s=new Sample(); s.method2("hello"); } }当我们运行java Sample命令时,java虚拟机会给每个线程分配方 法调用栈,用于跟踪每个线程调用方法的信息,同时方法调用栈 还用做线程的工作区,方法局部变量会存放到方法调用栈中线程的状态线程的状态在一个多线程运行环境中运行的线程可以有多种状态,也就是说一个线程在不同时刻会处于下列状态之一: 新建、就绪、运行、阻塞、终止; 线程生命周期中的5种状态线程生命周期中的5种状态新建:当一个 Thread 类或其子类对象被创建时,新产生的线程处于新建状态,此时它已经有了相应的内存空间和其他资源。如: Thread myThread=new MyThreadClass( ); 就绪:调用 start( ) 方法来启动处于新建状态的线程后,将进入线程队列排队等待 CPU 服务,此时它已经具备了运行的条件,一旦轮到它来享用 CPU 资源时,就可以脱离创建它的主线程,开始自己的生命周期。 运行:当就绪状态的线程被调度并获得处理器资源时,便进入运行状态。每一个 Thread 类及其子类的对象都有一个重要的 run( ) 方法,当线程对象被调用执行时,它将自动调用本对象的 run( ) 方法,从第一句开始顺序执行。Run( ) 方法定义了这个线程的操作和功能。线程生命周期中的5种状态:线程生命周期中的5种状态:阻塞:一个正在执行的线程暂停自己的执行而进入的状态。引起线程由运行状态进入阻塞状态的可能情况: 该线程正在等待 I/O 操作的完成 调用了该线程的 sleep( ) 方法 调用了 wait( ) 方法 让处于运行状态的线程调用另一个线程的join()方法线程生命周期中的5种状态:线程生命周期中的5种状态:对应于不同进入阻塞状态的情况,采取不同的方法使其回到就绪状态: I/O 操作:等待这个 I/O 操作完成后; sleep( ) 方法:等待其指定的休眠事件结束后,自动脱离阻塞状态; 调用 wait( ) 方法:调用 notify( ) 或 notifyAll( ) 方法; 线程生命周期中的5种状态:线程生命周期中的5种状态:终止: 自然终止:线程完成了自己的全部工作 强制终止:在线程执行完之前,调用 stop( ) 或 destroy( ) 方法终止线程 null线程的状态及转换创建一个新的线程创建一个新的线程Java中的多线程是建立在Thread类,Runnable接口的基础上的,通常有两种办法让我们来创建一个新的线程: 创建一个Thread类,或者一个Thread子类的对象; 创建一个实现Runnable接口的类的对象; nullname:线程的名称,target:要运行的线程对象,group:线程组的名称,stackSize:堆栈的大小Thread类介绍nullThread类介绍countStackFrames(); suspend(); resume(); stop(); stop(Throwable obj); Thread类的常用方法Thread类的常用方法currentThread():返回当前运行的Thread对象。 setName():设置线程的名字。 getName():返回该线程的名字。 setPriority():设置线程优先级。 getPriority():返回线程优先级。 start():启动一个线程。 run():线程体,由start()方法调用,当run()方法返回时,当前的线程结束。 stop():使调用它的线程立即停止执行。 isAlive():如果线程已被启动并且未被终止,那么isAlive():返回true。如果返回false,则该线程是新创建或是已被终止的。 Thread类的常用方法Thread类的常用方法sleep(int n):使线程睡眠n毫秒,n毫秒后,线程可以再次运行。 yield():将CPU控制权主动移交到下一个可运行线程。 join():方法join()将引起现行线程等待,直至方法join所调用的线程结束。 suspend(): 使线程挂起,暂停运行。 resume() 恢复挂起的线程,使其处于可运行状态(Runnable)。 wait(): notify(): notifyAll(): suspend(); resume(); Stop(); 目前已经不再使用。为什么?请看API.null因为Java线程的调度不是分时的,所以你必须确保你 的代码中的线程会不时地给另外一个线程运行的机会。 有三种方法可以做到一点: 让处于运行状态的线程调用Thread.sleep()方法。 让处于运行状态的线程调用Thread.yield()方法。 让处于运行状态的线程调用另一个线程的join()方法。sleep()和yield()的区别sleep()和yield()的区别这两个方法都是静态的实例方法。 yield()让运行中的线程主动放弃当前获得的CPU处理机会,但不是使该线程阻塞,而是使之转入就绪状态。 yield()给相同优先级或更高的线程运行机会,如果当前没有存在相同优先级的线程,则yield()什么都不做。而sleep()不会考虑线程的优先级,会给其他线程运行的机会,因此也会给相同或更低优先级线程运行机会。 sleep()使线程转入阻塞状态,而yield()使线程转入runnable状态。 sleep()会有中断异常抛出,而yiled()不抛出任何异常。 sleep()方法具有更好的可移植性,因为yield()的实现还取决于底层的操作系统对线程的调度策略。 对于yield()的主要用途是在测试阶段,人为的提高程序的并发性能,以帮助发现一些隐藏的并发错误,当程序正常运行时,则不能依靠yield方法提高程序的并发行能。null方法wait()与sleep() 方法一样,都能使线程等待而停止运行,其区别在于sleep()方法不会释放对象的锁,而wait()方法进入等待时,可以释放对象的锁,因而别的线程能对这些加锁的对象进行操作。所以,wait,notify和notifyAll都是与同步相关联的方法,只有在synchronized方法中才可以用。 在不同步的方法或代码中则使用sleep()方法使线程暂时停止运行。 null线程类Thread中提供以下几个版本的join()方法。 使当前正在运行的线程暂停下来,等待指定的时间后 或等待调用该方法的线程结束后,再恢复运行。 public final void join()throws InterruptedException; public final void join(long millis,int nanos)throws InterruptedException; public final void join(long millis)throws InterruptedException;join() 方法:举例:TestSubThread2.javanullpublic void timeout(){ // 暂停该线程,等候其他线程(tt)结束 tt.join(); // 其他线程结束后,继续进行该线程 …… …… }join():方法join()将引起现行线程等待,直至方法join 所调用的线程结束。nullnull将一个类定义为Thread的子类,那么这个类就可以 用来创建线程。 这个类中有一个至关重要的方法——public void run,这个方法称为线程体,它是整个线程的核心,线程所要完成任务的代码都定义在线程体中,实际上不同功能的线程之间的区别就在于它们线程体的不同举例:ThreadTester.java TestSubThread.java TestMyThread.java Example19_1.java UseThread.java应用线程类创建线程nullTimePrinter.javanullThread.sleep()方法的使用,注意异常的抛出nullnullnullnullnullnullnull主线程和其他线程共存nullnullThread.sleep()方法的使用,注意异常的抛出 nullnulljoin()方法的使用,注意异常的抛出。保证了主线程最后结束nullnullnullnull应用Runnable接口创建线程Runnable是Java中用以实现线程的接口,从根本 上讲,任何实现线程功能的类都必须实现该接口。 Thread(Runnable target); Thread(Runnable target, String name); Runnable接口中只定义了一个方法就是run()方法,也就是线程体。举例: TimePrinter1.java TestMyClassThread.java UseRunnable.java UseRunnable.htmlnullnullnullnullnull因为Java只允许单继承,如果一个类已经继承了Thread,就不能再继承其他类。 比如对于Applet程序,由于必须继承java. applet.Applet,因此就只能采取这种实现接口的方法。 特别是在除了run()方法以外,并不打算重写Thread类的其它方法的情况下,以实现Runnable接口的方式生成新线程就显得更加合理了。适用于采用实现Runnable接口方法的情况 终止线程 终止线程当线程执行完run()方法,它将自然终止运行。 Thread有一个stop()方法,可以强制结束线程,但这种方法是不安全的。因此,在JDK1.2开始的版本中,stop()方法已经被废弃。 实际编程中,一般是定义一个标志变量,然后通过程序来改变标志变量的值,从而控制线程从run()方法中自然退出。 null创建用户多线程的步骤(1)创建用户多线程的步骤(1)1.创建一个Thread类的子类 2.在子类中将希望该线程做的工作写到run()里面 3.生成该子类的一个对象 4.调用该对象的start()方法 class MyThread extends Thread{ public void run(){… …} //其它方法等 } class MyClass{ public static void main(String[] args){ MyThread mt = new MyThread(); mt.start(); } //其它方法等 }创建用户多线程的步骤(2)创建用户多线程的步骤(2)1.创建一个实现Runnable接口的类 2.在该类中将希望该线程做的工作写到run()里面 3.生成该类的一个对象 4.用上述对象去生成Thread类的一个对象 5.调用Thread类的对象的start()方法 class MyRunnable implements Runnable{ public void run(){… …} //其它方法等 } class MyClass{ public static void main(String[] args){ MyRunnable mr = new MyRunnable(); Thread t = new Thread(mr); t.start(); } //其它方法等 }创建用户多线程的步骤(3)创建用户多线程的步骤(3)1.创建一个实现Runnable接口的类 2.在该类中将希望该线程做的工作写到run()里面 3.写一个start()方法,在里面创建Thread,调用start() 4.生成Runnable类的一个对象 5.调用该类对象的start()方法 class MyRunnable implements Runnable{ public void run(){… …} public void start(){ new Thread(this).start(); } //其它方法等 } class MyClass{ public static void main(String[] args){ MyRunnable mr = new MyRunnable(); mr.start(); } //其它方法等 }线程的互斥锁和线程同步(synchronized)线程的互斥锁和线程同步(synchronized)多线程/同步(synchronized)多线程/同步(synchronized)在多线程环境中,两个或者两个以上的线程访问一个共享对象的情况是很普遍的 比如某公司在银行里有一个帐号,其在北京和上海的营业部都可以使用,那么如果北京的营业部在存款的时候,上海的营业部正好在取款,会发生什么事呢? 带着这个问题,我们再来看看多线程是怎样运行的: 各个线程是通过竞争CPU时间而获得运行机会的; 各线程什么时候得到CPU时间,占用多久,是不可预测的; 一个正在运行着的线程在什么地方被暂停是不确定的。 共享资源对象,如果不协调这些操作的话,就不能保证运行结果的正确。Data RacesData Racespublic class DataRace extends Thread { static int x; public void run() { for (int i = 0; i < 100000; i++) { x = x + 1; x = x – 1; } } public static void main(String[] args) { x = 0; for (int i = 0; i < 100000; i++) new DataRace().start(); System.out.println(x); // x not always 0! } }nullnullThreadDemo.javanull线程的互斥锁同步是一种保证共享资源完整性的手段; 具体作法是在代 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 原子操作的程序代码前加上synchronized标记,这样的代码被称为同步代码块。 Java中用关键字synchronized为共享资源加锁,在任何一个时 刻只能有一个线程能取得加锁对象的钥匙,对加锁对象进行操作。从而达到了对共享资源访问时的保护。synchronized关键字可以使用在: 1.一个成员方法上 2.一个静态方法上 3.一个语句块上nullnullThreadDemo1.javanullnullThreadDemo2.javanull关键字synchronized的使用方法(例)public synchronized void write(); 由synchronized关键字锁定的是一个对象,而不是一个方法, 一个线程调用某个对象的synchronized方法,就锁定了这个对象,直到它从这个方法中退出,才释放了这个锁定。因此,一旦一个对象被某个线程锁定了,它的所有synchronized方法就都不允许别的线程调用了。 如果一个线程调用该方法,则方法体中访问的对象都被锁定,不允许其他线程访问,以解决共享资源的访问冲突问题。public static synchronized int getValue(); 一个线程调用一个类的static synchronized方法,就锁定了这个类对象,也就控制了所有static synchronized方法。即类中所有的静态同步方法在每个时刻只有一个可以执行 nullsynchronized (obj) {… … } 一个线程进入由synchronized (obj) {…}修饰的程序块,就锁定了由obj指定的那个对象。一个对象在某一时刻只能被一个线程锁定; 一个类可以有多个对象,不同的对象可以被不同的线程锁定 一个线程可以锁定多个对象注意:关键字synchronized的使用方法(例)UnsynchPrint.javaSynchPrint.javaClock.javaClock.htmlnullnullnullnullThreadDemo3.javanullThreadDemo4.java能否在代码块和函数 之间形成同步呢? 答案是肯定的。同步 函数中的监视对象是 this,所以我们让代 码块中的监视对象改 为this就可以了。nullnull关键字synchronized可以作为JAVA方法修饰符,也可以作为JAVA方法内的语句。被它修饰的代码部分往往被描述为临界区。这使很多人认为,由于代码被syscharonized保护着,因此同一时刻只能有一个线程访问它。但这种观点是错误的。 对于JAVA类中的方法,关键字sysnchronized其实并不锁定该方法或该方法的部分代码,它只是锁定对象。 当synchronized被当做方法修饰符的时候,他所取得的lock将被交给方法调用者(某对象)。如果synchronized作用于某对象的引用,则取得的lock将交给该引用所指的对象。 对一个对象进行同步控制到底意味什么呢?它说明调用该方法的线程将会取得对象的lock。通过synchronized函数或者synchronized语句来申请对象A的lock的线程,在该lock被释放前无法获得满足。 因此,synchronized方法或synchronized区段内的代码在同一时刻下可有多个线程执行,只要是对不同的对象调用该方法就可以。 线程通信线程通信不同的线程执行不同的任务,如果这些任务有某种联系,线程之间必须能够通信,协调完成工作。例如生产者和消费者共同操作堆栈,当堆栈为空时,消费者无法取出产品,应该先 通知 关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知 生产者向堆栈中加入产品。当堆栈已满时,生产者无法继续加入产品,应该先通知消费者从堆栈中取出产品。 java.lang.Object类中提供了两个用于线程通信的方法: wait():执行该方法的线程释放对象的锁,Java虚拟机把该线程放到该对象的等待池中。该线程等待其他线程将它唤醒。 notify():执行该方法的线程唤醒在对象的等待池中等待的一个线程。Java虚拟机从对象的等待池中随机的选择一个线程,把它转到对象的锁池中。nullnull一般来说,每个共享对象的互斥锁存在两个队列,一个是 锁等待队列,另一个是锁申请队列,锁申请队列中的第一个 线程可以对该共享对象进行操作,而锁等待队列中的线程在 某些情况下将移入到锁申请队列。 下面比较一下wait()、notify()和notifyAll()方法: wait,nofity,notifyAll必须在已经持有锁的情况下执 行,所以它们只能出现在synchronized作用的范围内, 也就是出现在用synchronized修饰的方法或类中。 wait的作用:释放已持有的锁,进入等待队列. notify的作用:唤醒wait队列中的第一个线程并把它移 入锁申请队列 notifyAll的作用:唤醒wait队列中的所有的线程并把 它们移入锁申请队列.nullwait,notify,notifyAllwait,notify和notifyAll都是与同步相关联的方法,只有在synchronized方法中才可以用 例如: public synchronized void get(){ … … if(account.amount
本文档为【多线程程序设计】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_598109
暂无简介~
格式:ppt
大小:872KB
软件:PowerPoint
页数:0
分类:互联网
上传时间:2013-06-16
浏览量:21