




全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第九章 线程 9.1.1 定义线程 扩展java.lang.Thread类,重写run()方法。 Java代码 class MyThread extends Thread public void run() System.out.println(Important job running in MyThread); 实现java.lang.Runnable,实现run()方法。 Java代码 class MyRunnable implements Runnable public void run() System.out.println(Important job running in MyRunnable); Thread类希望run()方法不带任何变元,并且它将在单独的调用栈内为你执行这个方法。如果有run(String s)方法,Thread类不会为你调用该方法,而且即使你自己直接调用了他,执行也不会用一个不同的调用栈在一个新的执行线程中发生。他只会发生在与你发出调用的代码相同的调用栈中,就像任何其他不同的方法调用一样。 9.1.2 实例化线程 每个执行线程都是作为Thread类的一个实例开始的。 对于扩展Thread类而定义的线程实例化方式如下: MyThread t = new MyThread(); 对于实现Runnable接口而定义的线程实例化方式如下: Java代码 MyRunnable r = new MyRunnable(); Thread t = new Thread(r); Thread类本身也实现了Runnable(他又一个我们正在重写的run()方法)。因此能够将一个Thread传递给另一个Thread的构造函数 Thread t=new Thread(new MyThread(); Thread类的构造函数: Thread() Thread(Runnable target) Thread(Runnable target,String name) Thread(String name) 当线程已经被实例化但还没有启动时,该线程处于new state。此时该线程不能认为是alive的,一旦调用了start()方法,线程就被认为是alive的(即使run()方法可能还没有实际开始执行)在run()方法结束时,线程被认为是死的。isAlive()方法是判断县城是否已经启动但还没有完成run()方法的最佳方式。 9.1.3 启动线程 t.start(); 在调用start()方法后,发生: 启动新的执行线程(具有新的调用栈)。 线程从新状态转到可运行状态(runnable state)。 当线程获得执行机会时,会运行它的目标run()方法。 如果想如下所示: Thread t=new Thread(); t.run();/合法,但不会启动新的执行线程。而只是表示从线程当前正在执行的类调用run()方法。 Thread.currentThread()用来获取当前线程引用。 Thread.getName()用来获得线程的名字。 启动并运行多个线程: 每个线程都会启动,而且每个线程都将运行到结束。但是顺序,优先没有绝对保证。 当线程的目标run()方法结束时,该线程就完成了。死线程不能再次调用start()方法。/但是它仍然是一个Thread对象,如果具有对Thread实例的引用,则即使该Thread实例不再是一个执行线程,仍然能够调用这个Thread实例上的方法,就像任何其他Java对象一样 只要线程已经启动过,它就永远不能再次启动。/两次启动会导致IllegalThreadStateException这种RuntimeException异常。 线程调度器: 可运行线程变成运行中线程的顺序是没有保证的。 java.lang.Thread类中控制(影响)线程的方法: Java代码 public static void sleep(long millis) throws InterruptedException public static void yield() public final void join() throws InterruptedException public final void setPriority(int newPriority) /默认是5,值越大,优先越高 1-10 java.lang.Object类中控制(影响)线程的方法: Java代码 public final void wait() throws InterruptedException public final void notify() /唤醒单个线程 public final void notifyAll() /唤醒所有线程 9.2.1 线程状态 新状态-new 可运行状态-runable 运行中状态-running 等待/阻塞/睡眠状态-waiting/blocked/sleeping 死状态-dead 一些方法看起来像是在通知另一个线程阻塞,但其实不是。如果你有对另一个线程的引用,则可以编写像下面的代码:t.sleep()或者t.yield()。但这些是Thread的静态方法-他们不会影响实例t,这样定义,他们是为了影响当前正在执行的线程。 9.2.2 阻止线程执行 一个线程被踢出“运行中”状态,而不是被送回“可运行”或“死”状态。 即:睡眠,等待,因为需要对象的锁而被阻塞。 9.2.3 睡眠 Thread的两个静态方法: public static void sleep(long millis) throws InterruptedException /millis是毫秒 public static void sleep(long millis,int nanos) throws InterruptedException /nanos是纳秒 当线程的sleep()到期而醒来,并不意味着它将返回到运行中状态。当线程醒来时,它只会返回到可运行状态。当执行代码遇到sleep()调用时,他会让当前正在运行的线程睡眠。不要误以为一个线程能够使另一个线程睡眠。 9.2.4 线程优先级和yield() 调度器在优先级上是没有保证的,主要是看它“喜欢。还是不喜欢”,真够无奈的。 设置线程的优先级 t.setPriority(int i); yield()方法 Thread的静态方法yield(),让当前的“运行中”线程回到“可运行”状态,让步给具有相同优先级的其他“可运行”线程,但这是没有任何保证的。 join()方法 Thread的非静态方法join()让当前线程加入到引用的线程尾部,这意味着调用方法的线程完成(死状态)之前,主线程不会变为可运行的。 保证当前线程停止运行,直到它所加入的线程完成为止。然而,如果它加入的线程不是活得,则当前线程不需要停止。 public final void join() /要一直等待该线程结束 throws InterruptedException public final void join(long millis) /millis为0表示要一直等下去 throws InterruptedException/如果等待时间超过5秒,则无论如何停止等待,变成可运行状态。 public final void join(long millis, int nanos) throws InterruptedException 9.3 同步代码 9.3.1 同步和锁 synchronized 只能同步方法(或代码块),不能同步变量或类 每个对象只有一个锁。换句话说同一时间只有一个线程可以使用该对象的同步方法或代码块。 不必同步类中的全部方法。类可以同时具有同步方法和非同步方法。 一旦一个线程获得了对象的锁,就没有任何其他线程可以进入(该对象的)类中的任何同步方法。 如果类同时具有同步和非同步方法,则多个线程仍然能够访问该类的非同步方法。 如果线程进入睡眠,则它会保持已有的任何锁,不会释放他们。 线程可以获得多个锁,即线程可以同时获得多个对象的锁。/如果线程获得了锁,接着又试图在同一对象上调用同步方法时,JVM知道这个方法已经具有该对象的锁,因此使用这个线程已经拥有的锁,线程可以随意调用同一对象上的其他同步方法。 静态方法能否同步 可以,静态代码块也可以。例如: Java代码 public static synchronized int getCount() return count; public static int getCount() /注意synchronized关键字后面括号里的内容:即要锁的类或对象 synchronized(MyClass.class) return count; 如果线程不能获得锁会怎么样? 会阻塞,等锁释放。实质上,就是线程进入该对象的一个池内,必须在那里等待,直到锁释放,该线程才变成可运行状态。锁被释放不意味着任何特定的线程会得到它。 调用同一个类中非静态同步方法的线程将彼此阻塞,如果他们使用同一个实例进行调用的话。如果使用两个不同的实例调用它们,则他们会获得两个锁,且这两个锁互不干预。 调用同一个类中静态同步方法的线程将始终彼此阻塞-他们都锁定在同一个Class实例上 静态同步方法和非静态同步方法永远不会彼此阻塞。静态方法锁定在Class实例上,而非静态方法锁定在this实例上 对于同步块,在同一个对象上同步的线程将彼此阻塞,在不同的对象上同步的线程将不会彼此阻塞。 何时需要同步? 书云:对于复杂的情况“如果你不想它的话,你的生命就会更长、更愉快。真的如此,我们没有撒谎。” 线程安全类 StringBuffer等,但是不能完全依靠它来提供所需要的线程保护。 9.3.2 线程死锁 当代码等待从对象删除锁而迫使线程执行暂停时,死锁就发生了。 当被锁的对象试图访问另一个被锁的对象,而该对象又要访问第一个被锁的对象时,就会发生死锁现象。换句话说,两个线程都在等待对方释放锁,因此,这些锁永远不会释放! 死锁是一种糟糕的设计,不应当让它发生。 9.4 线程交互 必须在同步方法内调用wait()、notify()和notifyAll()方法!线程不能调用对象上的等待或通知方法,除非它拥有该对象的锁。 当调用wait()方法时,线程会立即放弃她在该对象上的锁。当调用notify()时,如果线程仍然在完成同步代码,则线程在移出同步代码前不会放弃锁 notifyAll()会通知在特定的锁定对象上等待的所有线程,而不是任何对象上等待的所有线程。 没有将对象同步前调用wait()方法,会引起IllegalMonitorStateException 9.4
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电信消防知识培训课件
- vi设计教学课件-b 下载
- 2025年建筑工程项目管理入门知识测试卷及答案
- 申论政务上云平台课件
- 甲状腺瘤的护理课件
- 各类麻醉术前术后护理5
- 甲乙类功率放大电路课件
- 《树的日子》教学课件
- 三维目标教学课件
- 统编版语文八年级上册第7课藤野先生练习题(含答案)
- 学院 军训协议书
- 农村房地产转让合同协议
- 拉链专业工艺讲解
- 快速康复在泌尿外科的应用
- (标准)按摩店转让合同协议书
- 《死亡医学证明(推断)书》培训试题(附答案)
- 护理核心制度2025年
- 膀胱灌注的护理课件
- 桥梁安全保护区管理制度
- 学堂在线 大学生国家安全教育 章节测试答案
- 2025至2030中国增强型飞行视觉系统行业发展趋势分析与未来投资战略咨询研究报告
评论
0/150
提交评论