实现runnable接口的类把我搞糊涂了,问一个能体现程序员功力的问题
/*代码原意是Game线程每隔0.3秒钟给int变量head加一,然后打印出来;TimeCounter线程在第1.5秒钟使Game线程等待3秒钟,然后Game线程重新运行,可是我的程序在运行时候Game线程并没有等待3秒钟,为什么呢?*/
class TimeCounter extends Thread {
Game game;
TimeCounter(Game g) {
game = g;
}
public void run() {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (game != null)
game.stop();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (game != null)
game.resume();
}
}
class Game implements Runnable {
// 只写重要的代码
int head;
Thread thread;
public void run() {
while (true) {
head++;
System.out.println(head);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void stop() {
try {
thread.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void resume() {
thread.notify();
}
public static void main(String[] args) {
Game game = new Game();
TimeCounter tc = new TimeCounter(game);
game.start();
tc.start();
}
}
[解决办法]
在TimeCounter线程中调用了game.stop()无形中是要让TimeCounter线程wait
可在Game类线程的运行模块中设置
- Java code
if (isStopped) { try { synchronized (thread) { thread.wait(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
[解决办法]
在一个线程里是不能直接控制另外一个线程的运行状态,你只能通过设置状态标志的方式来间接控制。
class TimeCounter extends Thread
{
Game game;
TimeCounter(Game g)
{
game = g;
}
public void run()
{
try
{
Thread.sleep(1500);
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
if(game != null)
{
game.setStop(true);
}
}
}
class Game implements Runnable
{
// 只写重要的代码
int head;
boolean stop;
Thread thread;
public void run()
{
while(true)
{
synchronized(this)
{
head++;
System.out.println(head);
try
{
if(stop)
{
this.wait(3000);
stop = false;
}
Thread.sleep(300);
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
public void start()
{
thread = new Thread(this);
thread.start();
}
public void setStop(boolean stop)
{
this.stop = stop;
}
public static void main(String[] args)
{
Game game = new Game();
TimeCounter tc = new TimeCounter(game);
game.start();
tc.start();
}
}
[解决办法]
调用wait和notify前必须获得对象的同步锁。
- Java code
synchronized (obj){ obj.wait(); //这里释放同步锁}
[解决办法]
哈哈,这个问题相当有意思,而且很典型!绕了一回才弄清楚怎么回事!
至于LZ的程序直接跑肯定有异常,因为wait方法要释放所有锁资源,所以它的调用前提是必须先获得对象锁资源,我修改了一下代码,可以跑了,不过现象很有趣,大家可以看看为什么会这样运行?是否知道真正的原因呢?
- Java code
class TimeCounter extends Thread { private Game game; public TimeCounter(Game g){ game = g; } public void run(){ try{ System.out.println("Counter waiting..."); Thread.sleep(1500); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println("stop begin..."); if(game != null) game.stop(); System.out.println("3000 begin..."); try{ Thread.sleep(3000); }catch(InterruptedException e){ e.printStackTrace(); } if(game != null) game.resume(); }} public class Game implements Runnable{ private int head; public void run(){ while(true){ head++; System.out.println("Head:"+head); try{ Thread.sleep(300); }catch(InterruptedException e){ e.printStackTrace(); } } } public void start(){ new Thread(this).start(); } public synchronized void stop(){ try{ System.out.println("waiting..."); this.wait(); }catch(InterruptedException e){ e.printStackTrace(); } } public void resume(){ System.out.println("notify..."); notify(); } public static void main(String[] args){ Game game = new Game(); TimeCounter tc = new TimeCounter(game); game.start(); tc.start(); } } //打印结果Head:1Counter waiting...Head:2Head:3Head:4Head:5stop begin...waiting...Head:6Head:7Head:8Head:9Head:10Head:11Head:12Head:13Head:14...一直Head下去了
[解决办法]
10楼的程序
在运行到this.wait();时把线程TimeCounter停在那里了 因为没别的线程执行notify() 所以这线程一直等下去了
而这个线程 new Thread(this).start(); 一直执行下去
10楼想说的是不是:
this.wait(); 这里停的并非 new Thread(this).start(); 这里产生的线程
但这好像不是楼主提出的问题吧 