java并发编程--一道经典多线程题的2种解法.docx_第1页
java并发编程--一道经典多线程题的2种解法.docx_第2页
java并发编程--一道经典多线程题的2种解法.docx_第3页
java并发编程--一道经典多线程题的2种解法.docx_第4页
java并发编程--一道经典多线程题的2种解法.docx_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

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

文档简介

问题的描述启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15. 接着再由线程1打印16,17,18,19,20.以此类推, 直到打印到75. 程序的输出结果应该为:线程1: 1线程1: 2线程1: 3线程1: 4 线程1: 5线程2: 6线程2: 7线程2: 8线程2: 9线程2: 10.线程3: 71线程3: 72线程3: 73线程3: 74线程3: 75解法一: 采用原始的synchronized, wait(), notify(), notifyAll()等方式控制线程.Java代码 1. publicclassNumberPrintDemo 2. /n为即将打印的数字 3. privatestaticintn=1; 4. /state=1表示将由线程1打印数字,state=2表示将由线程2打印数字,state=3表示将由线程3打印数字 5. privatestaticintstate=1; 6. 7. publicstaticvoidmain(Stringargs) 8. finalNumberPrintDemopn=newNumberPrintDemo(); 9. newThread(newRunnable() 10. publicvoidrun() 11. /3个线程打印75个数字,单个线程每次打印5个连续数字,因此每个线程只需执行5次打印任务.3*5*5=75 12. for(inti=0;i5;i+) 13. /3个线程都使用pn对象做锁,以保证每个交替期间只有一个线程在打印 14. synchronized(pn) 15. /如果state!=1,说明此时尚未轮到线程1打印,线程1将调用pn的wait()方法,直到下次被唤醒 16. while(state!=1) 17. try 18. pn.wait(); 19. catch(InterruptedExceptione) 20. e.printStackTrace(); 21. 22. /当state=1时,轮到线程1打印5次数字 23. for(intj=0;j5;j+) 24. /打印一次后n自增 25. System.out.println(Thread.currentThread().getName() 26. +:+n+); 27. 28. System.out.println(); 29. /线程1打印完成后,将state赋值为2,表示接下来将轮到线程2打印 30. state=2; 31. /notifyAll()方法唤醒在pn上wait的线程2和线程3,同时线程1将退出同步代码块,释放pn锁. 32. /因此3个线程将再次竞争pn锁 33. /假如线程1或线程3竞争到资源,由于state不为1或3,线程1或线程3将很快再次wait,释放出刚到手的pn锁. 34. /只有线程2可以通过state判定,所以线程2一定是执行下次打印任务的线程. 35. /对于线程2来说,获得锁的道路也许是曲折的,但前途一定是光明的. 36. pn.notifyAll(); 37. 38. 39. 40. ,线程1).start(); 41. 42. newThread(newRunnable() 43. publicvoidrun() 44. for(inti=0;i5;i+) 45. synchronized(pn) 46. while(state!=2) 47. try 48. pn.wait(); 49. catch(InterruptedExceptione) 50. e.printStackTrace(); 51. 52. for(intj=0;j5;j+) 53. System.out.println(Thread.currentThread().getName() 54. +:+n+); 55. 56. System.out.println(); 57. state=3; 58. pn.notifyAll(); 59. 60. 61. 62. ,线程2).start(); 63. 64. newThread(newRunnable() 65. publicvoidrun() 66. for(inti=0;i5;i+) 67. synchronized(pn) 68. while(state!=3) 69. try 70. pn.wait(); 71. catch(InterruptedExceptione) 72. e.printStackTrace(); 73. 74. for(intj=0;j5;j+) 75. System.out.println(Thread.currentThread().getName() 76. +:+n+); 77. 78. System.out.println(); 79. state=1; 80. pn.notifyAll(); 81. 82. 83. 84. ,线程3).start(); 85. 86. public class NumberPrintDemo / n为即将打印的数字private static int n = 1;/ state=1表示将由线程1打印数字, state=2表示将由线程2打印数字, state=3表示将由线程3打印数字private static int state = 1;public static void main(String args) final NumberPrintDemo pn = new NumberPrintDemo();new Thread(new Runnable() public void run() / 3个线程打印75个数字, 单个线程每次打印5个连续数字, 因此每个线程只需执行5次打印任务. 3*5*5=75for (int i = 0; i 5; i+) / 3个线程都使用pn对象做锁, 以保证每个交替期间只有一个线程在打印synchronized (pn) / 如果state!=1, 说明此时尚未轮到线程1打印, 线程1将调用pn的wait()方法, 直到下次被唤醒while (state != 1)try pn.wait(); catch (InterruptedException e) e.printStackTrace();/ 当state=1时, 轮到线程1打印5次数字for (int j = 0; j 5; j+) / 打印一次后n自增System.out.println(Thread.currentThread().getName()+ : + n+);System.out.println();/ 线程1打印完成后, 将state赋值为2, 表示接下来将轮到线程2打印state = 2;/ notifyAll()方法唤醒在pn上wait的线程2和线程3, 同时线程1将退出同步代码块, 释放pn锁. / 因此3个线程将再次竞争pn锁/ 假如线程1或线程3竞争到资源, 由于state不为1或3, 线程1或线程3将很快再次wait, 释放出刚到手的pn锁. / 只有线程2可以通过state判定, 所以线程2一定是执行下次打印任务的线程./ 对于线程2来说, 获得锁的道路也许是曲折的, 但前途一定是光明的.pn.notifyAll();, 线程1).start();new Thread(new Runnable() public void run() for (int i = 0; i 5; i+) synchronized (pn) while (state != 2)try pn.wait(); catch (InterruptedException e) e.printStackTrace();for (int j = 0; j 5; j+) System.out.println(Thread.currentThread().getName()+ : + n+);System.out.println();state = 3;pn.notifyAll();, 线程2).start();new Thread(new Runnable() public void run() for (int i = 0; i 5; i+) synchronized (pn) while (state != 3)try pn.wait(); catch (InterruptedException e) e.printStackTrace();for (int j = 0; j 5; j+) System.out.println(Thread.currentThread().getName()+ : + n+);System.out.println();state = 1;pn.notifyAll();, 线程3).start();解法二: 采用JDK1.5并发包提供的Lock, Condition等类的相关方法控制线程.Java代码 1. publicclassNumberPrintimplementsRunnable 2. privateintstate=1; 3. privateintn=1; 4. /使用lock做锁 5. privateReentrantLocklock=newReentrantLock(); 6. /获得lock锁的3个分支条件 7. privateConditionc1=lock.newCondition(); 8. privateConditionc2=lock.newCondition(); 9. privateConditionc3=lock.newCondition(); 10. 11. Override12. publicvoidrun() 13. newThread(newRunnable() 14. publicvoidrun() 15. for(inti=0;i5;i+) 16. try 17. /线程1获得lock锁后,其他线程将无法进入需要lock锁的代码块. 18. /在lock.lock()和lock.unlock()之间的代码相当于使用了synchronized(lock) 19. lock.lock(); 20. while(state!=1) 21. try 22. /线程1竞争到了lock,但是发现state不为1,说明此时还未轮到线程1打印. 23. /因此线程1将在c1上wait 24. /与解法一不同的是,三个线程并非在同一个对象上wait,也不由同一个对象唤醒 25. c1.await(); 26. catch(InterruptedExceptione) 27. e.printStackTrace(); 28. 29. /如果线程1竞争到了lock,也通过了state判定,将执行打印任务 30. for(intj=0;j5;j+) 31. System.out.println(Thread.currentThread().getName() 32. +:+n+); 33. 34. System.out.println(); 35. /打印完成后将state赋值为2,表示下一次的打印任务将由线程2执行 36. state=2; 37. /唤醒在c2分支上wait的线程2 38. c2.signal(); 39. finally 40. /打印任务执行完成后需要确保锁被释放,因此将释放锁的代码放在finally中 41. lock.unlock(); 42. 43. 44. 45. ,线程1).start(); 46. 47. newThread(newRunnable() 48. publicvoidrun() 49. for(inti=0;i5;i+) 50. try 51. lock.lock(); 52. while(state!=2) 53. try 54. c2.await(); 55. catch(InterruptedExceptione) 56. e.printStackTrace(); 57. 58. for(intj=0;j5;j+) 59. System.out.println(Thread.currentThread().getName() 60. +:+n+); 61. 62. System.out.println(); 63. state=3; 64. c3.signal(); 65. finally 66. lock.unlock(); 67. 68. 69. 70. ,线程2).start(); 71. 72. newThread(newRunnable() 73. publicvoidrun() 74. for(inti=0;i5;i+) 75. try 76. 77. lock.lock(); 78. while(state!=3) 79. try 80. c3.await(); 81. catch(InterruptedExceptione) 82. e.printStackTrace(); 83. 84. for(intj=0;j5;j+) 85. System.out.println(Thread.currentThread().getName() 86. +:+n+); 87. 88. System.out.println(); 89. state=1; 90. c1.signal(); 91. finally 92. lock.unlock(); 93. 94. 95. 96. ,线程3).start(); 97. 98. 99. publicstaticvoidmain(Stringargs) 100. newNumberPrint().run(); 101. 102. public class NumberPrint implements Runnable private int state = 1;private int n = 1;/ 使用lock做锁private ReentrantLock lock = new ReentrantLock();/ 获得lock锁的3个分支条件private Condition c1 = lock.newCondition();private Condition c2 = lock.newCondition();private Condition c3 = lock.newCondition();Overridepublic void run() new Thread(new Runnable() public void run() for (int i = 0; i 5; i+) try / 线程1获得lock锁后, 其他线程将无法进入需要lock锁的代码块./ 在lock.lock()和lock.unlock()之间的代码相当于使用了synchronized(lock)lock.lock();while (state != 1)try / 线程1竞争到了lock, 但是发现state不为1, 说明此时还未轮到线程1打印. / 因此线程1将在c1上wait/ 与解法一不同的是, 三个线程并非在同一个对象上wait, 也不由同一个对象唤醒c1.await(); catch (InterruptedException e) e.printStackTrace();/ 如果线程1竞争到了lock, 也通过了state判定, 将执行打印任务for (int j = 0; j 5; j+) System.out.println(Thread.currentThread().getName()+ : + n+);System.out.println();/ 打印完成后将state赋值为2, 表示下一次的打印任务将由线程2执行state = 2;/ 唤醒在c2分支上wait的线程2c2.signal(); finally / 打印任务执行完成后需要确保锁被释放, 因此将释放锁的代码放在finally中lock.unlock();, 线程1).start();new Thread(new Runnable() public void run() for (int i = 0; i 5; i+) try lock.lock();while (state != 2)try c2.await(); catch (InterruptedException e) e.printStackTrace();for (int j = 0; j 5; j+) System.out.print

温馨提示

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

评论

0/150

提交评论