Java线程及多线程技术及应用_第1页
Java线程及多线程技术及应用_第2页
Java线程及多线程技术及应用_第3页
Java线程及多线程技术及应用_第4页
Java线程及多线程技术及应用_第5页
已阅读5页,还剩26页未读 继续免费阅读

付费下载

下载本文档

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

文档简介

1、第 6 章 Java 线程及多线程技术及应用6.1 线程基本概念1、进程和线程的基础知识进程:运行中的应用程序称为进程,拥有系统资源(cpu 、内存)线程: 进程中的一段代码, 一个进程中可以哦有多段代码。 本身不拥有资源 (共享 所在进程的资源) 在 java 中,程序入口被自动创建为主线程,在主线程中可以创建多个子线程。 区别: 1、是否占有资源问题2、创建或撤销一个进程所需要的开销比创建或撤销一个线程所需要的开销大。3、进程为重量级组件,线程为轻量级组件多进程 : 在操作系统中能同时运行多个任务(程序 )多线程 : 在同一应用程序中有多个功能流同时执行2、线程的主要特点不能以一个文件名的

2、方式独立存在在磁盘中; 不能单独执行,只有在进程启动后才可启动; 线程可以共享进程相同的内存(代码与数据)。3、线程的主要用途利用它可以完成重复性的工作(如实现动画、声音等的播放)。 从事一次性较费时的初始化工作(如网络连接、声音数据文件的加载)。 并发执行的运行效果(一个进程多个线程)以实现更复杂的功能4、多线程(多个线程同时运行)程序的主要优点可以减轻系统性能方面的瓶颈,因为可以并行操作; 提高CPU勺处理器的效率,在多线程中,通过优先级管理,可以使重要的程序优先 操作,提高了任务管理的灵活性;另一方面,在多CPU系统中,可以把不同的线程在不同的CPI中执行,真正做到同时处理多任务。6.2

3、 线程创建与启动1、与线程编程有关的一些概念创建方式: 1 继承 java.lang.Thread 类 2 实现 java.lang.Runnable 接口线程体:public void run()方法,其内的程序代码决定了线程的行为和功能。线程启动: public void start () , 线程启动后,需要获取 cpu 才能自动调用 run ()运行。 线程休眠: public void sleep(long ms), 线程将暂停,放弃 cpu2、禾U用继承Thread类创建线程的示例package com.px1987.j2se.thread.base;/*通过Thread类实现多线

4、程定义一个Thread的子类并重写其run方法.*/public class MyThread extends Thread 0verridepublic void run() while (true) System.out.println("invoke MyThread run method");public static void main(String args) / main方法测试线程的创建与启动MyThread myThread = new MyThread();/ 实例化 MyThread 的对象myThread.start();/ 调用myThread 对

5、象的start方法启动一个线程3、利用实现 Runable接口创建线程的示例package com.px1987.j2se.thread.base;/*通过Runable 接口实现多线程 定义MyRunable 类实现 Runnable接口,并实现接口中的run方法。*/public class MyRunable implements Runnable public void run() while (true)System.out.println("invoke MyRunable run method");public static void main(String

6、args) / main方法测试线程的创建与启动/ 建立MyRunable类的对象,以此对象为参数建立Thread 类的对象Thread thread = new Thread(new MyRunable();thread.start();/ 调用 thread 对象的 start方法启动一个线程6.3线程的状态控制1、新建状态用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runn able)。2、就绪状态处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列,等

7、待系统为其分配 CPU。等待状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动作称之为“pu调度” 一旦获得CPU,线程就进入运行状态并自动调用自己的run方法。3、死亡状态死亡状态是线程生命周期中的最后一个阶段。线 程死亡的原因有两个:stop或destroy方法来终止一个线程。Method stop() & destroy。in the class Thread is deprecated。当一个线程进入死亡状态以后,就不能再回到其它状态了。 执行一次的唯一方法,就是重新产生一个Thread对象。4、体现线程状态转变的代码

8、示例创建让一个Thread对象重新package com.px1987.j2se.thread.base;public class MyRunable1 implements Runnable public void run() while (true)System.out.println("invoke MyRunable run method");public static void main(String args) Thread thread = new Thread(new MyRunable();/ 新生状态thread.start();/ 就绪状态,获得 CP

9、U后就能运行try Thread.sleep(5000); catch (InterruptedException e) e.printStackTrace(); thread.stop();/ 死亡状态通过查API可以看到stop方法和destory方法已经过时了,所以不能再用,那要怎样做 才能强制的销毁一个线程呢?1、在run方法中执行return线程同样结束2、可以在while循环的条件中设定一个标志位,当它等于 运行,这样线程也就结束了。代码为实现的代码示例:false的时候,while循环就不在package com.px1987.j2se.thread.StateControl;p

10、ublic class MyRunable2 implements Runnable private boolean isStop;/线程是否停止的标志位public void run() while (!isStop)System.out.println("invoke MyRunable run method");public void stop() isStop=true;/终止线程public static void main(String args) MyRunable myRunable=new MyRunable();Thread thread = new T

11、hread(myRunable);thread.start();try Thread.sleep(5000);catch (InterruptedException e) e.printStackTrace();myRunable.stop();/正确的停止线程的方法5、阻塞状态处于运行状态的线程在某些情况下,如执行了 sleep(睡眠)方法,或等待 I/O设备等资源,将让出 CPU并 暂时停止自己的运行,进入阻塞状态。在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的

12、位置开始继续运行。有三种方法可以暂停Threads执行:(1)sleep 方法可 以调用 Thread 的静态方法: public static void sleep(long millis) throws InterruptedException使得当前线程休眠(暂时停止执行 millis毫秒)。由于是静态方法,sleep 可以由类名直接调用: Thread.sleep(,)。下面为代码示例:package com.px1987.j2se.thread.p5;import java.util.Date;import java.text.SimpleDateFormat;class Sleep

13、Test implements Runnable private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-ddhh:mm:ss");public void run() System.out.println("child thread begin");int i = 0;while (i+ < 5) System.out.println(format.format(new Date();try Thread.sleep(5000);catch (Interrupte

14、dException e) e.printStackTrace();Date();System.out.println("childthread dead at: " + format.format(newpublic static void main(String args) Runnable r = new SleepTest();Thread thread = new Thread(r);thread.start();try Thread.sleep(20000);catch (InterruptedException e) e.printStackTrace();t

15、errupt();System.out.println("main method dead!");该程序的运行结果如下:child thread begin2009-02-06 04:50:292009-02-06 04:50:342009-02-06 04:50:392009-02-06 04:50:44main method dead!java .l angn terruptedException: sleep interruptedat java.lang.Thread.sleep(Native Method)at com.px1987.j2se.t

16、hread.p5.Thread4.run(Thread4.java:17)at java .l ang.Thread.run(Unknown Source)2009-02-06 04:50:49child thread dead at: 2009-02-06 04:50:54(2) yield 方法让出CPU的使用权,从运行态直接进入就绪态。下面为代码示例:package com.px1987.j2se.thread.StateControl;class Thread5 implements Runnable private String name;Thread5(String s) this

17、.name = s;public void run() for (int i = 1; i <= 50; i+) System.out.println(name + ": " + i);if (i % 10 = 0) Thread.yield();package com.px1987.j2se.thread.StateControl; public class YieldTest public static void main(String args) Runnable r1 = new Thread5("S1"); Runnable r2 = n

18、ew Thread5("S2"); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start();t2.start();try Thread.sleep(2);catch (InterruptedException e) e.printStackTrace();System.out.println("main method over!");该程序的部分运行结果如下:S1:20S2:7S2:8S2:9S2:10S1:41S1:42S1:43S1:44S1:45S1:46S1:47S1:

19、48S1:49S1:50S2:11S2:123)join方法当某个(A)线程等待另一个线程(B)执行结束后,才继续执行时,使用join方法。A的run 方法调用 b.join() 。下面为代码示例。package com.px1987.j2se.thread.join;class FatherThread implements Runnable public void run() System.out.println("爸爸想抽烟,发现烟抽完了 ");System.out.println("爸爸让儿子去买包红塔山 ");Thread son = new

20、Thread(new SonThread(); son.start(); System.out.println(" 爸爸等儿子买烟回来 "); try /join 含义:等待 son 线程执行完毕, father 线程才继续执行 son.join();catch (InterruptedException e) System.out.println(" 爸爸出门去找儿子跑哪去了 "); System.exit(1);System.out.println(" 爸爸高兴的接过烟开始抽,并把零钱给了儿子 ");package com.px1

21、987.j2se.thread.join;class SonThread implements Runnable public void run() String tabs="tttttt"System.out.println(tabs+"儿子出门去买烟 ");System.out.println(tabs+"儿子买烟需要 10 分钟 ");try for (int i = 0; i < 10;) Thread.sleep(1000); System.out.println(tabs+"儿子出去第 " + +

22、i + "分钟 "); catch (InterruptedException e) e.printStackTrace(); System.out.println(tabs+" 儿子买烟回来了 "); package com.px1987.j2se.thread.join; public class JoinTest public static void main(String args) System.out.println(" 爸爸和儿子的故事 "); Thread father = new Thread(new FatherT

23、hread(); father.start();/try /Thread.sleep(5000);/ catch (InterruptedException e) /e.printStackTrace();/errupt(); 该程序的运行结果如下: 爸爸和儿子的故事 爸爸想抽烟,发现烟抽完了 爸爸让儿子去买包红塔山 爸爸等儿子买烟回来儿子出门去买烟儿子买烟需要 10 分钟儿子出去第 1 分钟儿子出去第 2 分钟 儿子出去第 3 分钟 儿子出去第 4 分钟 儿子出去第 5 分钟 儿子出去第 6 分钟 儿子出去第 7 分钟 儿子出去第 8 分钟 儿子出去第 9 分钟 儿子出去

24、第 10 分钟 儿子买烟回来了 爸爸高兴的接过烟开始抽,并把零钱给了儿 子 当时间来到儿子出去买烟的时候, Father 线程调用 interrupt 方法就会打断 son 线程的正 常执行,从而 father 线程也就不必等待 son 线程执行完毕再行动了,运行结果如下: 爸爸和儿子的故事 爸爸想抽烟,发现烟抽完了 爸爸让儿子去买包红塔山 爸爸等儿子买烟回来儿子出门去买烟儿子买烟需要 10 分钟儿子出去第 1 分钟儿子出去第 2 分钟 儿子出去第 3 分钟 儿子出去第 4 分钟 爸爸出门去找儿子跑哪去了1、线程的基本信息方法 isAlive() getPriority()6.4 线程的调度和

25、优先级功能判断线程是否还“活”着,即线程是否还未终止。 获得线程的优先级数值setPriority()设置线程的优先级数值setName()给线程一个名字getName()取得线程的名字currentThread()取得当前正在运行的线程对象,也就是取得自己本身2 、操作线程的基本信息代码示例 package com.px1987.j2se.thread.priority;public class ThreadInfoTest public static void main(String argc) throws Exception Runnable r = new MyThread();Th

26、read t = new Thread(r, "Name test"); t.start();System.out.println("name is: " + t.getName(); Thread.currentThread().sleep(5000);System.out.println(t.isAlive(); System.out.println("over!");class MyThread implements Runnable public void run() for (int i = 0; i < 100; i

27、+) System.out.println(i); 该程序的运行结果如下: name is: Name test0123979899falseover!3、线程的优先级(1)优先级(共 10 级): 它们决定线程 执行的先后 次序(优 先级高者 先执行)并 可以通过 Thread 类 中的 setPriority() 和 getPriority ()方法来改变和获取优先级。典型的优先级码Thread.MIN_PRIORITY (1 级) Thread.MAX_PRIORITY ( 10 级) Thread.NORM_PRIORITY ( 5 级)2)调度规则Java 是不支持线程时间片轮换的调

28、度模型, 而采用的是线程优先级高低的抢占调度模型。具有高优先级的线程可以抢占低优先级线程运行的机会。高优先级的线程将始终 获得线程执行时间。但是这也不是绝对的, java 线程调度器有可能会调用长期处于等待 的线程进行执行,所以不要依靠线程的高优先级抢占模型去完成某些功能。Java 线程调度器支持不同优先级线程的抢先方式, 但其本身不支持相同优先级线程 的时间片轮换。但是如果 java 运行时系统所在的操作系统(如 windows2000 )支持时间 片的轮换,则线程调度器就支持相同优先级线程的时间片轮换。(3)代码示例package com.px1987.j2se.thread.priori

29、ty;public class ThreadPriorityTest public static void main(String args) Thread t1 = new Thread(new MyThread2(), "t1");Thread t2 = new Thread(new MyThread2(), "t2");t1.setPriority(1);t2.setPriority(10);t1.start();t2.start();class MyThread2 extends Thread public void run() for (int

30、 i = 0; i < 10; i+) System. out .println(Thread. currentThread().getName() + ": " + i);yield ();该程序的运行结果如下:t1: 0t2: 0t2: 1t2: 2t2: 3t2: 4t2: 5t2: 6t2: 7t2: 8t2: 9t1: 1t1: 2t1: 3t1: 4t1: 5t1: 6t1: 7t1: 8t1: 96.5线程同步互斥1、线程同步互斥的一个示例多个线程同时访问或操作同一资源时,很容易出现数据前后不一致的问题。请看下面的例子:男孩拿着折子去北京银行海淀分行取钱

31、女孩拿着男孩的银行卡去西单百货疯狂购物男孩走到柜台钱询问帐户余额银行的业务员小姐亲切地告诉他:“您还有10000元!"。女孩看上了一件时髦的衣裳,准备买下男孩在思考要取多少钱呢?女孩到收银台准备刷卡消费收银台刷卡机读取银行卡余额为10000元女孩买衣服刷卡消费5000元消费清单打印出来,消费:5000元 余额:5000 元女孩离开商场男孩思考了 1毫秒男孩决定取5000元银行的业务员小姐为男孩办理相关业务手续交易完成银行的业务员小姐告诉男孩:“您的余额为5000元“。男孩离开银行男孩帐户中一共有10000元,男孩拿着存折从银行取走5000元,女孩拿着男孩的银行卡购物刷卡消费 5000

32、元,最后男孩的帐户里却还剩5000元。显然这是不正确的,但是为什么会发生这样的情况呢?我们可以这样分析:男孩可以看作是一条线程,女孩也可以看作是一条线程,在同一时刻,两个线程都操作了同一个资源,那就是男孩的帐户。男孩从查看帐户余额到取走现金应该被看作是个原子性操作,是不可再分的,然而当男孩查看完余额正思考取多少钱的时候,女孩购物消费了5000元,也就是说女孩这条线程打断了男孩这条线程所要执行的任务。所以男孩刚查看完的余额10000元就不正确了,最终导致帐户中少减了5000 元。为了避免这样的事情发生,我们要保证线程 同步互斥,所谓同步互斥就是: 并发执行的多个线程在某一时间内只允许一个线程在执

33、行以访问共享数据2、Java中线程互斥的实现机制由多线程带来的性能改善是以可靠性为代价的,所以编程出线程安全的类代码是十分 必要的。当多个线程可以访问共享资源(调用单个对象的属性和方法,对数据进行读、写、 修改、删除等操作)时,应保证同时只有一个线程访问共享数据,Java对此提出了有效的解决方案一同步锁。任何线程要进入同步互斥方法(访问共享资源的方法或代码段)时,就必须得到这个共享资源对象的锁,线程进入同步互斥方法后其它线程则不能再进入同步互斥方 法,直到拥有共享资源对象锁的线程执行完同步互斥方法释放了锁,下一个线程才能进入同步互斥方法被执行。Java的这一线程互斥的实现机制可以用一个最通俗的

34、比方来说明:比如公共卫生间就是一个共享资源,每个人都可以使用, 但又不能同时使用, 所以卫生间里有一把锁。 一个人 进去了,会把门锁上,其他人就不能进去。当Ta出来的时候,要打开锁,下一个人才能继续使用。3、利用Synchronized关键字用于修饰同步互斥方法(1)同步互斥方法public synchroni zed void method()/ 允许访问控制的代码(2 )同步互斥代码块synchroni zed(s yn cObject)/允许访问控制的代码(3)锁定整个类public syn chro ni zed class Syn cObject由于synchronized块可以针对

35、任意的代码块,且可任意指定上锁的对象,因此灵活性较 高。但要注意:synchronized可以用来限定一个方法或一小段语句或整个类(该类中的所有方法都是 synchronized 方法)将访问共享数据的代码设计为synchronized方法由于可以通过private关键字来保证数据对象只能被方法访问,所以只需针对方法提出一套同步锁定机制。通过sy nchroni zed方法来控制对类中的成员变量(共享数据)的访问。编写线程安全的代码会使系统的总体效率会降低,要适量使用只有某一个线程的synchronized方法执行完后其它线程的synchronized方法才能被执行。当前时间,只有一个线程访问

36、被锁定的代码段,但不能保证其他线程去访问其他没有被锁定的代码段。因此所有对共享资源进行操作的代码段都应该加锁。对数据库操作时,修改数据的线程要加锁,而读数据的线程可以不加锁有了这种解决方案,我们用线程安全的代码来重新实现一下男孩和女孩取钱的故事。以下是核心代码:package com.px1987.j2se.thread.synchronous.v2;/* 帐户类*/public class Account /* 余额*/private int balance;public Account(int balance) this.balance = balance;package com.px19

37、87.j2se.thread.synchronous.v2;/* 男孩类,实现 Runnable 接口 */public class Boy implements Runnable /* 银行帐户 */Account account;public Boy(Account account) this.account = account;/* 男孩拿着折子去北京银行海淀分行取钱 */public void run() System. out .println(" 男孩拿着折子去北京银行海淀分行取钱 ");synchronized (account) System. out .p

38、rintln(" 男孩走到柜台钱询问帐户余额 ");int balance = account.getBalance();System. out .println(" 银行的业务员小姐亲切地告诉他: " 您还有 " +balance + " 元! " 。 ");try System. out .println(" 男孩在思考要取多少钱呢? ");Thread. sleep (1);System. out .println(" 男孩思考了 1 毫秒 ");catch (Inte

39、rruptedException e) e.printStackTrace();int money = 5000;System. out .println("男孩决定取 " + money + "元 ");System. out .println(" 银行的业务员小姐为男孩办理相关业务手续 "); account.setBalance(balance - money);System. out .println(" 交易完成 ");System. out .println(" 银行的业务员小姐告诉男孩: &

40、quot; 您的余额为 " +account.getBalance()+ "元 " 。 ");System. out .println(" 男孩离开银行 ");package com.px1987.j2se.thread.synchronous.v2;/* 女孩类,实现 runnable 接口 */public class Girl implements Runnable /* 女孩持有男孩的银行卡 */Account account; public Girl(Account account) this.account = accou

41、nt;/* " 女孩拿着小军的银行卡去西单百货疯狂购物 */String tabs = "tttttt"System. out .println(tabs + "System. out .println(tabs + " synchronized (account) System. out .println(tabs + int balance = account.getBalance(); System. out .println(tabs + " 元");int payout = 5000;System. out .pr

42、intln(tabs + " account.setBalance(balance - payout); System. out .println(tabs + "public void run() 女孩拿着小军的银行卡去西单百货疯狂购物 "); 女孩看上了一件时髦的衣裳,准备买下 ");女孩到收银台准备刷卡消费 ");收银台刷卡机读取银行卡余额为 " + balance + "女孩买衣服刷卡消费 " + payout + "元 ");消费清单打印出来,消费: " + payout +

43、 "元" +" 余额: " + account.getBalance() + "元 ");System. out .println(tabs + "女孩离开商场 ");package com.px1987.j2se.thread.synchronous.v2;public class Bank public static void main(String args) Account account=new Account(10000);Thread boyThread=new Thread(new Boy(acco

44、unt);Thread girlThread=new Thread(new Girl(account);boyThread.start(); girlThread.start();女孩拿着小军的银行卡去西单百货疯狂购女孩看上了一件时髦的衣裳,准备买下 女孩到收银台准备刷卡消费 收银台刷卡机读取银行卡余额为 10000 元 女孩买衣服刷卡消费 5000 元 消费清单打印出来, 消费: 5000 元 余额:修改后的代码运行结果如下图: 男孩拿着折子去北京银行海淀分行取钱物5000 元女孩离开商场男孩走到柜台钱询问帐户余额银行的业务员小姐亲切地告诉他:“您还有5000元!"。男孩在思考要取

45、多少钱呢?男孩思考了 1毫秒男孩决定取5000元银行的业务员小姐为男孩办理相关业务手续交易完成银行的业务员小姐告诉男孩:“您的余额为0元“。男孩离开银行从结果中可以看出来,男孩从查看余额到取钱,女孩没有操作帐户,所以最后的余额是正确的。4、线程死锁使用互斥锁容易产生死锁问题。比如:一个线程需要锁定两个对象才能完成,线程1拥有对象A的锁,线程1如果再拥有对象 B的锁就能完成操作,线程2拥有对象B的锁,线程2如果再拥有对象 A的锁就能完成操作。很不幸的是线程1执行不下去了,因为线程 1等待的资源对象 B被线程2锁住了,线 程2也执行不下去了,因为线程2等待的资源对象 A被线程1锁住了,这样就造成了

46、死锁。阅读一段文字:由多线程带来的性能改善是以可靠性为代价的,主要是因为有可能产生线程死锁。死 锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线 程被无限期地阻塞,因此程序不能正常运行。简单的说就是:线程死锁时,第一个线程等待第二个线程释放资源,而同时第二个线程又在等待第一个线程释放资源。这里举一个通俗的例子:如在人行道上两个人迎面相遇,为了给对方让道,两人同时向一侧迈岀一步,双方无法通过,又同时向另一侧迈出一步,这样还是无法通过。假设这种情况一直持续下去,这样就会发生死锁现象。导致死锁的根源在于不适当地运用“ syn chro nized关键词来管理线

47、程对特定对象的访问。“ syn chro nized关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被 允许执行的线程首先必须拥有对变量或对象的排他性访问权。当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁。(1)死锁问题的一个代码示例package com.px1987.j2se.thread.DeadLock;class Thread1 implements Runnable private Object a;private Object b;public Thread1(Object a, Obj

48、ect b) super();this.a = a;this.b = b;public void run() synchronized (a) System. out .println("Thread1try Thread. sleep (1);catch (InterruptedException e) e.printStackTrace();synchronized (b) System. out .println("Thread1 try Thread. sleep (1); catch (InterruptedException e) e.printStackTra

49、ce();package com.px1987.j2se.thread.DeadLock;class Thread2 implements Runnable private Object a;private Object b;public Thread2(Object a, Object b) super();this.a = a;this.b = b;public void run() synchronized (b) System. out .println("Thread2try Thread. sleep (1);catch (InterruptedException e)

50、e.printStackTrace();synchronized (a) System. out .println("Thread2 try Thread. sleep (1); catch (InterruptedException e) e.printStackTrace();获得对象 a 的锁 ");获得对象 b 的锁 ");获得对象 b 的锁 ");获得对象 a 的锁 ");package com.px1987.j2se.thread.DeadLock;public class TestDeadLock public static vo

51、id main(String args) Object a=new Object();Object b=new Object();Thread thread1=new Thread(new Thread1(a,b);Thread thread2=new Thread(new Thread2(a,b); thread1.start();thread2.start();下面是运行结果:Thr e ad 1获得对隊q的锁Threads获得对象b的锁(2)死锁问题的另一个代码示例package com.px1987.j2se.thread.DeadLock;public class ThreadDea

52、dLock public static void main(String args) ThreadOne threadOne=new ThreadOne();ThreadTwo threadTwo=new ThreadTwo();String s1="s"String s2="sss"threadOne.op仁s1;threadTwo.op仁s1;threadOne.op2=s2;threadTwo.op2=s2;threadOne.start();threadTwo.start();class ThreadOne extends ThreadStrin

53、g op1;String op2;public void run()同步中又有同步,就可能死锁synchronized(op1)锁定op1");System.out.println(Thread.currentThread().getName()+" try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace();synchronized(op2)System.out.println(Thread.currentThread().getName()+" 锁 定 op2"

54、);class ThreadTwo extends ThreadString op1;String op2;public void run()synchronized(op2)System.out.println(Thread.currentThread().getName()+" 锁定 op2");try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace();synchronized(op1)System.out.println(Thread.currentThread().getNa

55、me()+" 锁 定 op1");6.6 生产者消费者问题1、生产者消费者问题的示例生产者消费者问题也是一个典型的线程问题。 我们举一个这方面的实例来说明: 在一个 果园里,有农夫和小孩,农夫会不停的采摘水果放入果园中心的一个水果筐直到水果筐满, 而小孩会不停的从水果筐里拿水果来吃, 直到水果拿完。 分析这个模型我们可以看出: 农夫 可以看成是一个生产者的线程, 小孩可以看成是一个消费者的线程, 而大水果筐是共享资源。 2 、用 Java 程序表述的代码示例package com.px1987.j2se.thread.ProducerConsumer;import java.util.Random;/* 水果类 */public class Fruit /* 水果编号 */private int id;/* 水果编号计数器 */private static int number = 0;/* 水

温馨提示

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

评论

0/150

提交评论