JAVA多线程
那天在后院输入”线程“关键字,结果只找到hjack的一篇文章,可见这里讨论”线程“不多。这几天正好在看JAVA多线程设计,所以发个帖,大家来讨论讨论。我们学习编程的时候,第一个程序的功能常常是输出 "HelloWrold"。
如果第一次写多线程程序,这也算是第一个HelloWrold程序了。
class Test
{
public static void main(String[]args)
{
new Thread(){
public void run()
{
for(int i=0;i<1000;i++)
System.out.print("Hello ");
}
}.start();
for(int i=0;i<1000;i++)
System.out.print("world ");
}
}
在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要求先得到笔接着得到纸就可以写一行字,然后也放开笔,纸。程序代码如下:
class Main
{
public static void main(String[]args)
{
String pen=new String("pen");
String paper=new String("paper");
new Test("A",pen,paper).start();
new Test("B",paper,pen).start();
}
}
class Test extends Thread
{
private final String pen;
private final String paper;
private String name;
public Test(String name,String pen,String paper)
{
this.name=name;
this.pen=pen;
this.paper=paper;
}
public void run()
{
while (true)
{
write();
}
}
public void write()
{
synchronized(pen)
{
System.out.println(name+" pick up the "+pen+"!");
synchronized(paper)
{
System.out.println(name+" pick up the "+paper+"!");
System.out.println(name+" write a line!");
System.out.println(name+" put down the "+paper+"!");
}
System.out.println(name+" put down the "+pen+"!");
}
}
}
执行结果:
A pick up the pen!
A pick up the paper!
A write a line!
A put down the paper!
A put down the pen!
A pick up the pen!
A pick up the paper!
A write a line!
A put down the paper!
B pick up the paper!
A put down the pen!
B pick up the pen!
B write a line!
B put down the pen!
B put down the paper!
B pick up the paper!
B pick up the pen!
B write a line!
B put down the pen!
B put down the paper!
B pick up the paper!
B pick up the pen!
B write a line!
B put down the pen!
B put down the paper!
B pick up the paper!
A pick up the pen!
在B拿到纸,A拿到笔时停住了。
如果把
new Test("A",pen,paper).start();
new Test("B",paper,pen).start();
改成
new Test("A",pen,paper).start();
new Test("B",pen,paper).start();
就不会发生死锁了。原因是A拿了pen,B也想拿pen,(虽然有paper也不去拿)只有等A放下pen。这样就不会出现一个在等pen一个在等paper的情况了。
对于多线程,我是初学,不对之处请见谅! 楼主写得不错.支持原创,支持分享... 银行家算法 呵呵.
当时有想过写写一些多线程方面的贴,
但一直很忙,没有时间去搞.
现在更加忙.
powerwind ,加油!
相信你可以做得到(还记得我的PM吗?)
Immutable问题
Immutable就没问题了。Immutable就是不可变的意思,String类就是最典型Immutable类。上面讨论到的线程死锁问题中,如果将pen和paper封装起来就不会发生死锁。但是封得要够死,(如果内部给悄悄改了就不好)也就是封成Immutable类。为了说明Immutable类,说个简单的例子。String类是Immutable类,StringBuffer是mutable类
//Immutable的Message类
class Message
{
private final String msg;
public Message(String msg)
{
this.msg=msg;
}
public String toString()
{
return "Message:"+msg;
}
}
//mutable的Message类
class Message
{
private final StringBuffer msg;
public Message(StringBuffer msg)
{
this.msg=msg;
//改成这样(this.msg=new StringBuffer(msg))也可以变成immutable
}
public String toString()
{
return "Message:"+msg;
}
}
//测试类
class Main
{
public static void main(String[]args)
{
StringBuffer sb=new StringBuffer("Hello");
//String sb=new String("Hello");
Message message=new Message(sb);
System.out.println(message);
//sb.replace("Hello","world");
sb.replace(0,5,"world");
System.out.println(message);
}
}
//改变注释,可是看到,一个在外面给改了,一个无法改。
如果写多线程的程序时发现运行不是所期望的,可以考虑是不是有些东西在外部给改变了。我感觉这个问题应该在C++中更易出现,因为它的指针权力太大了。(猜测而已)
页:
[1]