ImageVerifierCode 换一换
格式:DOCX , 页数:30 ,大小:108.05KB ,
资源ID:10167643      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10167643.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(多线程.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

多线程.docx

1、多线程多线程程序:是计算机指令的集合.程序是一组静态的指令集,不占用系统运行资源,不能被系统调度,也不能作为独立运行的单位,它以文件的形式存储在磁盘上。进程:是一个程序在其自身的地址空间中的一次执行活动。比如,打开一个记事本,就是调用了一个进程。进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,一个程序可以对应多个进程。线程:又称为轻量级进程,是进程中的一个单一的连续控制流程。它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单一个进程可以拥有多个

2、线程。多线程优点:可以更好的实现并行。 恰当地使用线程时,可以降低开发和维护的开销,并且能够提高复杂应用的性能。 CPU在线程之间开关时的开销远比进程要少得多。因开关线程都在同一地址空间内,只需要修改线程控制表或队列,不涉及地址空间和其他工作。 创建和撤销线程的开销较之进程要少。多线程的性能比多进程高,在实际工作中如果需要在有限的时间内出来完大量的数据,可以考虑开启多个线程,比如电信项目每个月末需要计算所有的话单量,假设总的话单量有4000万,为了提高效率,可以考虑开启4个进程或者4个线程。依次进行处理,比如第一个进程处理1-1000万,第二个进程处理1001到-2000万,依次类推。也可以考

3、虑开启多个线程,第一个线程处理1-1000万,第二个线程处理1001到-2000万,依次类推。在同样资源的情况下开启多个线程的效率是大于开启多个进程的。因为线程之间通过对CPU的抢占可以实现资源共享,而进程之间无法实现资源共享。可能有的进程内存不够,而有的线程又用不完。Java在语言级提供了对多线程程序设计的支持。多线程操作会增加程序的执行效率。各线程之间切换执行,时间比较短,看似是多线程同时运行,但对于执行者CPU来说,某一个时刻只有一个线程在运行。只是CPU切换的过程比较快,感觉像是多个线程并行。那么单线程和多线程之间到底有什么区别呢?先看一个单线程的例子:public class Sin

4、gleThread public static void main(String args) SingleThread singleThread = new SingleThread(); singleThread.run(); while(true) System.out.println(in the main method.); public void run() while(true) System.out.println(in the run method.); 以上函数的run方法中有个while(true),判断条件永远为真,所以持续会打印in the run method.字符串

5、,入口函数中的in the main method.永远不会被执行到。下面看一个多线程的实例, public class MutipleThread extends Thread public static void main(String args) MutipleThread singleThread = new MutipleThread(); singleThread.start(); while(true) System.out.println(in the main method.); public void run() while(true) System.out.println

6、(in the run method.); 运行程序打印结果:in the main method.in the run method.in the main method.in the run method.in the main method.in the run method.in the main method.in the run method.in the main method.in the run method.in the run method.以上就是一个多线程的实例,与单线程相比,区别是1. 类继承(extends)Thread2. 通过调用start()方法启动线程,而

7、不是直接调用run方法。注意以上“in the main method.”与“in the run method.”不一定会按照特定的顺序输出,因为不确定谁会抢占到CPU编写线程编写线程有2中方法Extends Thread不管是以上的哪种方式,都必须要提供run方法。Thread是线程里面的基类,如果我们想要编写多线程,可以继承它。在编写多线程的时候必须要提供一个run方法,run方法是多线程的入口方法,相当我们常用的main入口函数。调用多线程程序时必须要通过调用start方法来启动线程。先看一个最基本的多线程实例public class FirstThread extends Threa

8、d public static void main(String args) FirstThread firstThread = new FirstThread(); firstThread.start(); public void run() System.out.println(first thread.); 打印结果:first thread.一般情况下需要使用多线程来做的任务一般情况下是需要比较常的运行时间,为了体现出多线程的特点经常会在run方法中写入死循环或者for循环语句。实际上多数的的服务器比如在学习java EE时讲到的Tomcat 启动后就是一个死循环的多线程。如果想要持续

9、提供给外部服务,就必须一直在运行。Implements Runnable使用实现Runnable 的方式需要继承Runnable,产生实现了Runnable 接口的对象,把产生的对象传递给Thread在调用Thread 的start 方法即可。public class ImplementsRunnableDemo implements Runnable public static void main(String args) ImplementsRunnableDemo ird =new ImplementsRunnableDemo(); Thread thread = new Thread(

10、ird); thread.start(); public void run() while(true) System.out.println(in the run method.); 以上两种方法都是通过调用start 来启动一个线程,可以产生多个多线程对象,通过在每个对象上调用start方法,就可以启动多个线程,注意不能在一个对象上调用两次start方法否则会出现:java.lang.IllegalThreadStateException通过以上实现多线程的两种方式大家对多线程应该有了大概的了解。使用extends 继承以后不能在继承其他的类,如果使用implements 还可以继续在继承其

11、他的类。在做实际的使用中使用第2种的情况比较多。那么为什么要提供2种不同的方式呢?他们之间到底有什么样的区别的。下面会详细解释。现在还是从继承Thread 入手 public class ExtendsThreadDemo extends Thread private int amount = 10; public static void main(String args) ExtendsThreadDemo etd0 = new ExtendsThreadDemo(); etd0.start(); ExtendsThreadDemo etd1 = new ExtendsThreadDemo(

12、); etd0.start(); public void run() while(amount0) System.out.println(amount:+(amount-); 运行程序打印输出:amount:10amount:9amount:8amount:7amount:6amount:5amount:4amount:3amount:2amount:1amount:10amount:9amount:8amount:7amount:6amount:5amount:4amount:3amount:2amount:1以上程序中定义一个amount 的实例变量,运行的时候先来判断amount的值,如

13、果大于0则进行减操作。由于在入口函数中产生了两个ExtendsThreadDemo对象,则存在两个amount实例,并且都是从10依次递减到1.下面在使用implements Runnable 来实现。public class ImplementsRunnableDemo implements Runnable private int amount = 10; public static void main(String args) ImplementsRunnableDemo ird =new ImplementsRunnableDemo(); Thread thread0 = new Th

14、read(ird); thread0.start(); Thread thread1 = new Thread(ird); thread1.start(); public void run() while(amount0) System.out.println(amount:+(amount-); 运行程序打印输出:amount:10amount:9amount:8amount:7amount:6amount:5amount:4amount:3amount:2amount:1以上程序中只产生了一个ImplementsRunnableDemo 实例,仅有一个amount 实例变量,所以虽然我们开

15、启了2个线程,但实际上操作的是同样一个amount。所以只有一个从10到1的打印输出。第2中比较典型的应用更是卖票系统,请大家思考下火车站在卖车票的时候可能开启了多个窗口,但是实际上卖的都在卖用样的一组车票,同一个列出上不可能出现2次2车厢22号座位。在这种情况下一定需要使用第2种方式实现。新线程:当利用new关键字创建线程对象实例后,它仅仅作为一个对象实例存在,JVM没有为其分配CPU时间片和其他线程运行资源; 就绪状态:在处于创建状态的线程中调用start方法将线程的状态转换为就绪状态。这时,线程已经得到除CPU时间之外的其它系统资源,只等JVM的线程调度器按照线程的优先级对该线程进行调度

16、,从而使该线程拥有能够获得CPU时间片的机会。 运行态:就绪态的线程获得cpu就进入运行态等待/阻塞:线程运行过程中被剥夺资源或者,等待某些事件就进入等待/阻塞状态,suspend()方法被调用 ,sleep()方法被调用,线程使用wait()来等待条件变量;线程处于I/O等待等,调用suspend方法将线程的状态转换为挂起状态。这时,线程将释放占用的所有资源,但是并不释放锁,所以容易引发死锁,直至应用程序调用resume方法恢复线程运行。 等待事件结束或者得到足够的资源就进入就绪态 死亡状态:当线程体运行结束或者调用线程对象的stop方法后线程将终止运行,由JVM收回线程占用的资源。Slee

17、p在多线程运行的时候,可能遇到某个线程持续处于运行状态,其他线程没有机会运行,为了让其他线程有机会执行,可是使用Sleep方法,该方法的作用就是使当前线程暂时停止运行,让其他线程有更多的机会执行。注意当我们调用了某个sleep方法的时候是处在了blocked状态,如果线程想再次进入运行状态必须从blocked 到ready状态,而不是从blocked直接进入running状态。就相当于在参加赛跑的中场,可能会休息一段时间,休息完后再到起跑点做好跑的动作,然后听到哨声响起再跑,而不会休息完后,从凳子上起来立刻就跑。在Thread中有个Thread.currentThread().getName(

18、),可以通过该方法得到当前运行线程的名字。看以下程序:public class SleepDemo implements Runnable public static void main(String args) SleepDemo sd =new SleepDemo(); Thread thread0 = new Thread(sd); thread0.start(); Thread thread1 = new Thread(sd); thread1.start(); public void run() while(true) System.out.println(currentThread

19、:+Thread.currentThread().getName(); currentThread:Thread-1currentThread:Thread-1currentThread:Thread-1currentThread:Thread-1currentThread:Thread-1currentThread:Thread-0currentThread:Thread-1currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0

20、currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:Thread-0currentThread:

21、Thread-0currentThread:Thread-0从上面的程序中可以发现有时Thread-0 执行很长时间,有时Thread-1运行较长时间,能不能使两个线程有比较公平的机会输出呢?也就是说不能让其中的某个线程一直占用了CPU。下面先run中增加一个sleep方法。public class SleepDemo implements Runnable public static void main(String args) SleepDemo sd =new SleepDemo(); Thread thread0 = new Thread(sd); thread0.start(); T

22、hread thread1 = new Thread(sd); thread1.start(); public void run() while(true) try Thread.sleep(10); catch (InterruptedException e) / TODO Auto-generated catch block e.printStackTrace(); System.out.println(currentThread:+Thread.currentThread().getName(); 运行结果:currentThread:Thread-0currentThread:Thre

23、ad-1currentThread:Thread-0currentThread:Thread-1currentThread:Thread-0currentThread:Thread-1currentThread:Thread-1currentThread:Thread-0currentThread:Thread-0currentThread:Thread-1currentThread:Thread-1currentThread:Thread-0currentThread:Thread-0currentThread:Thread-1currentThread:Thread-1currentThr

24、ead:Thread-0currentThread:Thread-0currentThread:Thread-1从运行结果已经可以看出Thread-0与Thread-1有比较平均的运行机会,但是注意不能够确保一定交替运行, 因为CPU是处于抢占的,而且从抢到到运行还有个过程,在多线程中不能够保证先start的线程先得到执行。Synchronized在启动多个线程的情况下,有可能存在线程抢占资源的情况,使程序出现错误,先看以下实例。public class SleepDemo implements Runnable int amount = 10; public static void main

25、(String args) SleepDemo sd =new SleepDemo(); Thread thread0 = new Thread(sd); thread0.start(); Thread thread1 = new Thread(sd); thread1.start(); public void run() while(amount0) try Thread.sleep(10); catch (InterruptedException e) / TODO Auto-generated catch block e.printStackTrace(); System.out.pri

26、ntln(amount:+(-amount); 运行结果:amount:9amount:8amount:7amount:6amount:5amount:4amount:3amount:2amount:1amount:0amount:-1由于启动过了两个线程,当amount=1时,第一个线程满足条件进入sleep,第二个线程线程进入了while判断, 此时由于第一个线程仍处在sleep阶段,还没有执行amount操作,此时amount 仍等于1, 当第一个线程执行amount操作后,amount=0,但是此时第二个线程已经进入while判断,并且又执行了-amount操作,最后amount =-

27、1;如何避免这样的问题?如果在amount 操作之前不让第二个线程进入即可避免这样的问题,在java提供了代码同步来实现,在同一时间内只有一个线程执行某段代码,这就是代码同步,synchronized 。下面对以上代码进行重构如下:public class SleepDemo implements Runnable int amount = 10; public static void main(String args) SleepDemo sd =new SleepDemo(); Thread thread0 = new Thread(sd); thread0.start(); Thread

28、 thread1 = new Thread(sd); thread1.start(); public synchronized void run() while(amount0) try Thread.sleep(10); catch (InterruptedException e) / TODO Auto-generated catch block e.printStackTrace(); System.out.println(amount:+(-amount); 运行结果:amount:9amount:8amount:7amount:6amount:5amount:4amount:3amount:2amount:1amount:0以上代码只是在run方法上加了一个synchronized 关键字,该关键字的作用就是在某段时间内只有一个线程执行run方法,如果当前线程没有执行run方法,别的线程都不能进入run方法执行。在此例中必须是-amount操作执行完后,别的线程才能进行while(amount0)判断。当把synchronized 关键字放在方法上时,称之为同步方法。我们可以选择同步代码块的方式来实现代码同步。重构以上代码如下所示:public class SleepDem

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1