工大后院

 找回密码
 加入后院

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
查看: 1936|回复: 4

JAVA多线程

[复制链接]
发表于 2006-4-21 13:32 | 显示全部楼层 |阅读模式
那天在后院输入”线程“关键字,结果只找到hjack的一篇文章,可见这里讨论”线程“不多。这几天正好在看JAVA多线程设计,所以发个帖,大家来讨论讨论。


我们学习编程的时候,第一个程序的功能常常是输出 "HelloWrold"。
如果第一次写多线程程序,这也算是第一个HelloWrold程序了。

  1. class Test
  2. {
  3.         public static void main(String[]args)
  4.         {
  5.                 new Thread(){
  6.                         public void run()
  7.                         {
  8.                                 for(int i=0;i<1000;i++)
  9.                                 System.out.print("Hello ");
  10.                         }
  11.                 }.start();

  12.                 for(int i=0;i<1000;i++)
  13.                 System.out.print("world ");

  14.         }
  15. }
复制代码


在main方法中写了一个匿名类,run方法会输出1000个Hello。乍一看,以为输出结果是先1000个Hello,然后1000个world。实际上呢,是Hello与world交错出现。这是因为我们启动了两个线程,这两个线程会交替获得CPU时间来执行操作。
这两个线程分别是:main方法是主线程,然后它又调用Thread类的start(),从而启动了另一个线程。(注意:如果调用Thread类的run(),不会启动新线程。详情请参考JDK文档)

多线程设计首先要注意控制好多线程之间的共享与冲突。其中Single Threaded Execution Pattern是多线程程序设计的基础,不过关于这个问题在
<<JAVA多线程设计模式--Single Threaded Execution Pattern>>(http://gdutbbs.com/thread-59348-1-1.html)有详细介绍。

下面就举一例,说明线程死锁的问题。
一个人写字,要有纸和笔。假设A要求先得到笔接着得到纸就可以写一行字,然后放开纸,笔。B要求先得到笔接着得到纸就可以写一行字,然后也放开笔,纸。程序代码如下:

  1. class Main
  2. {
  3.         public static void main(String[]args)
  4.         {
  5.                 String pen=new String("pen");
  6.                 String paper=new String("paper");
  7.                 new Test("A",pen,paper).start();
  8.                 new Test("B",paper,pen).start();
  9.         }
  10. }
  11. class Test extends Thread
  12. {
  13.         private final String pen;
  14.         private final String paper;
  15.         private String name;
  16.        
  17.         public Test(String name,String pen,String paper)
  18.         {
  19.                 this.name=name;
  20.                 this.pen=pen;
  21.                 this.paper=paper;
  22.         }

  23.         public void run()
  24.         {
  25.                 while (true)
  26.                 {
  27.                         write();
  28.                 }
  29.         }

  30.         public void write()
  31.         {
  32.                 synchronized(pen)
  33.                 {
  34.                         System.out.println(name+" pick up the "+pen+"!");
  35.                         synchronized(paper)
  36.                         {
  37.                                 System.out.println(name+" pick up the "+paper+"!");
  38.                                 System.out.println(name+" write a line!");
  39.                                 System.out.println(name+" put down the "+paper+"!");
  40.                         }
  41.                         System.out.println(name+" put down the "+pen+"!");
  42.                 }
  43.         }

  44. }
复制代码


执行结果:

  1. A pick up the pen!
  2. A pick up the paper!
  3. A write a line!
  4. A put down the paper!
  5. A put down the pen!
  6. A pick up the pen!
  7. A pick up the paper!
  8. A write a line!
  9. A put down the paper!
  10. B pick up the paper!
  11. A put down the pen!
  12. B pick up the pen!
  13. B write a line!
  14. B put down the pen!
  15. B put down the paper!
  16. B pick up the paper!
  17. B pick up the pen!
  18. B write a line!
  19. B put down the pen!
  20. B put down the paper!
  21. B pick up the paper!
  22. B pick up the pen!
  23. B write a line!
  24. B put down the pen!
  25. B put down the paper!
  26. B pick up the paper!
  27. A pick up the pen!
复制代码

在B拿到纸,A拿到笔时停住了。
如果把
       

  1.                 new Test("A",pen,paper).start();
  2.                 new Test("B",paper,pen).start();
  3.                
复制代码

                改成
       

  1.                 new Test("A",pen,paper).start();
  2.                 new Test("B",pen,paper).start();
  3.                
复制代码

                就不会发生死锁了。原因是A拿了pen,B也想拿pen,(虽然有paper也不去拿)只有等A放下pen。这样就不会出现一个在等pen一个在等paper的情况了。

对于多线程,我是初学,不对之处请见谅!
发表于 2006-4-21 16:50 | 显示全部楼层
楼主写得不错.支持原创,支持分享...
回复

使用道具 举报

发表于 2006-4-21 16:53 | 显示全部楼层
银行家算法
回复

使用道具 举报

发表于 2006-4-21 19:18 | 显示全部楼层
呵呵.

当时有想过写写一些多线程方面的贴,

但一直很忙,没有时间去搞.

现在更加忙.

powerwind ,加油!

相信你可以做得到(还记得我的PM吗?)
回复

使用道具 举报

 楼主| 发表于 2006-4-22 11:18 | 显示全部楼层

Immutable问题

Immutable就没问题了。Immutable就是不可变的意思,String类就是最典型Immutable类。上面讨论到的线程死锁问题中,如果将pen和paper封装起来就不会发生死锁。但是封得要够死,(如果内部给悄悄改了就不好)也就是封成Immutable类。为了说明Immutable类,说个简单的例子。
String类是Immutable类,StringBuffer是mutable类


  1. //Immutable的Message类
  2. class Message
  3. {
  4.         private final String msg;
  5.         public Message(String msg)
  6.         {
  7.                 this.msg=msg;
  8.         }

  9.         public String toString()
  10.         {
  11.                 return "Message:"+msg;
  12.         }
  13. }
复制代码

  1. //mutable的Message类
  2. class Message
  3. {
  4.         private final StringBuffer msg;
  5.         public Message(StringBuffer msg)
  6.         {
  7.                 this.msg=msg;
  8. //改成这样(this.msg=new StringBuffer(msg))也可以变成immutable
  9.         }
  10.         public String toString()
  11.         {
  12.                 return "Message:"+msg;
  13.         }
  14. }
复制代码

  1. //测试类
  2. class Main
  3. {
  4.         public static void main(String[]args)
  5.         {
  6.                 StringBuffer sb=new StringBuffer("Hello");
  7.                 //String sb=new String("Hello");
  8.                 Message message=new Message(sb);
  9.                 System.out.println(message);
  10.                 //sb.replace("Hello","world");
  11.                 sb.replace(0,5,"world");
  12.                 System.out.println(message);
  13.         }
  14. }
  15. //改变注释,可是看到,一个在外面给改了,一个无法改。
复制代码

如果写多线程的程序时发现运行不是所期望的,可以考虑是不是有些东西在外部给改变了。我感觉这个问题应该在C++中更易出现,因为它的指针权力太大了。(猜测而已)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入后院

本版积分规则

QQ|Archiver|手机版|小黑屋|广告业务Q|工大后院 ( 粤ICP备10013660号 )

GMT+8, 2024-5-16 22:03

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表