关于synchronized!

imtoy 2012-03-18 12:03:44
各位谁知道我这程序怎么一直都一个线程工作啊?去掉synchronized后多线程。怎么回事啊?

class TestSynchronized
{
public static void main(String[] args)
{
Ticket t = new Ticket();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}

class Ticket implements Runnable
{
int ticket = 100;
String str = new String("");
public void run()
{
while(true)
{
/*synchronized(str)
{
if(ticket > 0)
{
try
{Thread.sleep(100);}
catch(Exception e){}
System.out.println(Thread.currentThread().getName() + " :sales a ticket:" + ticket--);
}
}*/
sale();
}
}

public synchronized void sale()
{
if(ticket > 0)
{
try{Thread.sleep(100);}
catch(Exception e){}
System.out.println(Thread.currentThread().getName() + " :sales a ticket:" + ticket--);
}
}
}
...全文
98 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
imtoy 2012-03-18
  • 打赏
  • 举报
回复
我试过无数遍了,确实是只有第一个new出来的线程运行,很纳闷,就算是线程睡眠的时候其他线程不能运行,其他时间总能让别的线程运行吧?
nmyangym 2012-03-18
  • 打赏
  • 举报
回复
楼主的程序,为什么就出现单一线程在运行呢?
或许是运行时间短的原因。理论上是三个线程都有机会运行的。但楼主程序的问题是,在同步方法里,虽然运行Thread.sleep(100), 但别的线程并不能在此时运行,因为这个同步对象的锁不释放。
要象解决问题,很简单:把休眠放在同步方法的外边。


public class TestSynchronized
{
public static void main(String[] args)
{
Ticket t = new Ticket();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}

class Ticket implements Runnable
{
int ticket = 100;
String str = new String(""); //这个str用于同步目的。
public void run()
{
while(true)
{
try
{
Thread.sleep(100);
}
catch(Exception e)
{
e.printStackTrace(); // 最好加上.
}
synchronized(str)
{
if(ticket > 0)
{
System.out.println(Thread.currentThread().getName() + " :sales a ticket:" + ticket--);
}
}

if(ticket<=0) //票卖完让程序退出。
break;
}//end while
}//end run

}


nmyangym 2012-03-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 imtoy 的回复:]

我试过无数遍了,确实是只有第一个new出来的线程运行,很纳闷,就算是线程睡眠的时候其他线程不能运行,其他时间总能让别的线程运行吧?
[/Quote]
其实,三个线程都启动了. 这个可以通过在run()方法里加一句:
System.out.println("当前线程是: "+Thread.currentThread().getName());
看出来。
我们看到的是进入同步方法里的线程,确实我们这样看到的结果是就一个总能进入同步方法里。这说明那两个线程总是不容易得到同步对象的锁,他们被阻塞在那个"Object's wait pool" 里,等那个同步对象锁,但总是不易得到。
我在测试时,直接输出到屏幕上,看到的是一个线程在卖票。
象下面的情况:
[Quote=引用 2 楼 imtoy 的回复:]

我试过无数遍了,确实是只有第一个new出来的线程运行,很纳闷,就算是线程睡眠的时候其他线程不能运行,其他时间总能让别的线程运行吧?
[/Quote]
其实,三个线程都启动了. 这个可以通过在run()方法里加一句:
System.out.println("当前线程是: "+Thread.currentThread().getName());
看出来。
我们看到的是进入同步方法里的线程,确实我们这样看到的结果是就一个总能进入同步方法里。说明那两个线程总是不容易得到同步对象的锁,他们被阻塞在那个"Object's wait pool" 里,等那个同步对象锁,还总是不易得到。
我测试时,直接在屏幕输出,结果都是象这样:
当前线程是: Thread-0
当前线程是: Thread-2
当前线程是: Thread-1
Thread-0 :sales a ticket:100
Thread-0 :sales a ticket:99
Thread-0 :sales a ticket:98
....
....
....
Thread-0 :sales a ticket:3
Thread-0 :sales a ticket:2
Thread-0 :sales a ticket:1

中间省略的都是一样.

而如果我们把输出转向到一个文件,java csdn.thread.TestSynchronized>1.txt
我们打开1.txt 时看到的是这样:
当前线程是: Thread-0
当前线程是: Thread-1
当前线程是: Thread-2
Thread-0 :sales a ticket:100
Thread-0 :sales a ticket:99
Thread-0 :sales a ticket:98
Thread-0 :sales a ticket:97
Thread-2 :sales a ticket:96
Thread-2 :sales a ticket:95
Thread-2 :sales a ticket:94
Thread-2 :sales a ticket:93
Thread-2 :sales a ticket:92
Thread-2 :sales a ticket:91
Thread-2 :sales a ticket:90
Thread-2 :sales a ticket:89
Thread-2 :sales a ticket:88
Thread-2 :sales a ticket:87
Thread-2 :sales a ticket:86
Thread-2 :sales a ticket:85
Thread-2 :sales a ticket:84
Thread-2 :sales a ticket:83
Thread-2 :sales a ticket:82
Thread-2 :sales a ticket:81
Thread-1 :sales a ticket:80
Thread-1 :sales a ticket:79
Thread-1 :sales a ticket:78
Thread-1 :sales a ticket:77
Thread-1 :sales a ticket:76
...
三个线程都能进入同步方法里了,我猜想可能的原因是: 在进入同步方法前尽量让线程有一段时间,能够让其他线程获得抢占(或被调度的机会).

楼主自己试试看.
....
jiutian_good 2012-03-18
  • 打赏
  • 举报
回复
我试过了,你让程序多运行几次就不是只有一个线程了

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧