94% 通过SCJP考试,给大家散点分,同时仍有问题一起讨论!讨论者有分!

LJava 2003-12-10 04:31:52
昨天,考完试一共错了3道题,考试时觉得自己很有把握的,可是还是错了,为了让大家以后可以少犯错,所以和大家讨论一道题:),我错了以下这3个方面的题:1:Declarations and access control,2:Operators and Assignments,3:Threads.但不知道具体是错在哪道题上了,其中考了147中的一道线程题我非常怀疑,以前因为很多人都编译和修改过147的答案,所以自己没有完全编译过147中的题,现在看来147答案还是有一些问题的,大家不要都完全相信147的答案,要自己编译才好。以下是我为147第57题编的一段代码,编译通过。不知道能否说明此题,欢迎大家来讨论一下!

public class SyncTest_57 { //147-57t
public int x;
public int y; //为了方便看到 X,Y的值,我把它改为了PUBLIC,不影响结果!

private synchronized void setX (int i) {x=i;}
private synchronized void setY (int i) {y=i;}
public void setXY(int i){setX(i); setY(i);}
public synchronized boolean check() {return x != y;}
}

class Test1 implements Runnable{
private SyncTest_57 st;

public Test1(SyncTest_57 st){
this.st=st;
}
public void run(){
st.setXY(2);
//st.setY(3);
System.out.println(st.check());
System.out.println("X="+st.x+" Y="+st.y);
try{
Thread.sleep(500);
}catch(InterruptedException e){}

} //end run();
} // end class Test1;

class ThreadTest{
public static void main(String args[]){
SyncTest_57 st57=new SyncTest_57();

Test1 t1=new Test1(st57);
Thread thread1=new Thread(t1);
thread1.start();

Test1 t2=new Test1(st57);
Thread thread2=new Thread(t2);
thread2.start();

Test1 t3=new Test1(st57);
Thread thread3=new Thread(t3);
thread3.start();

Test1 t4=new Test1(st57);
Thread thread4=new Thread(t4);
thread4.start();

}
}
147 答案是B,我认为这道题应该选A,虽然setXY方法不是同步的,但其调用的方法是同步的,所以选A,不知道大家是否赞同,欢迎的大家讨论,指正错误!希望能使大家学到东西!
...全文
37 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
panpan221 2004-01-01
  • 打赏
  • 举报
回复
努力奋斗!
寒冬 2004-01-01
  • 打赏
  • 举报
回复
学习
badground 2003-12-28
  • 打赏
  • 举报
回复
to czf825(czf825)
跨实例运行线程我认为是不可能的,这个线程仅仅获得了一个对象的reference
它怎么可以去操作别的reference所索引的对象呢?

badground 2003-12-28
  • 打赏
  • 举报
回复
上面有个笔误,line5 “如果“应该去掉。


badground 2003-12-28
  • 打赏
  • 举报
回复
其实直接从运行线程的最基本的概念出发也可以解答这个问题
所有的问题都集中在
public void setXY(int i){setX(i); setY(i);}这一段
在这里setX和setY都是同步的方法,但是他们之间并不是同步的(虽然这里没有代码),也
就是说,如果线程在运行完setX这个方法后会释放它所拥有的lock,假设这时线程的时间片
还没有到期,那么它就继续下面的代码,首先重新获得lock然后运行setY,但如果在setX完成
线程释放lock以后,它的时间片刚好到期,那么下一个线程就会获得lock而对实例变量进行修改,这样就有可能发生x,y不相等的情况。

在setX(i); setY(i);之间加入一个很大的循环就可以看到这种结果。
xfr_1982 2003-12-25
  • 打赏
  • 举报
回复
下次回复,不过恭喜楼主。
czf825 2003-12-24
  • 打赏
  • 举报
回复
等待楼主的回复!!
LJava 2003-12-23
  • 打赏
  • 举报
回复
谢谢 大家的参与,大家的回复我要再研究一下再回复!因为最近好忙?呵呵
EinsteinXV 2003-12-21
  • 打赏
  • 举报
回复
贴太长了,下次回复,不过恭喜楼主。
我急,先走!
DESL 2003-12-21
  • 打赏
  • 举报
回复
努力学习中...
ustcfrank 2003-12-21
  • 打赏
  • 举报
回复
恭喜,学习
czf825 2003-12-21
  • 打赏
  • 举报
回复
一口气写了那么多,不知道对楼主是否有帮助......

天开始亮了,我真的要休息了,各位晚安......
czf825 2003-12-21
  • 打赏
  • 举报
回复
继上.....


那么,为什么楼上grgh2000(太阳)兄弟所提供的例程得不到"true"结果呢?请看我下面的分析:我们把注意力集中在“syncTest = new SyncTest();”和“Thread ts = new TestSync("A"+i);”两条语句上。grgh2000(太阳)兄弟每创建一条线程,就会同时创建一个新的syncTest类实例,而X和Y是syncTest类里面的成员变量,也就是说,每创建一条线程,系统就会重新为X和Y分配新的内存空间,这样,创建N条线程,就会有N个具有X和Y变量的syncTest实例同时被创建了,而每条线程所对应的只是跟它一起创建的那个syncTest实例,换句话说:每条线程都有它“自己”的X、Y、setXY()、setX()及setY();因此,在这种情况下,我认为线程是不会跨实例运行的(这句话有待证实),而只能在自己的实例里运行,所以按照程序中setXY()和check()的执行顺序可知,check()方法将永远是"false"!!

好,现在我们回头看一下上面的两条例程,它们都有一个共同的特点,那就是程序所创建的线程都是指向同一个实例!!这时候,线程之间就有了共同的X、Y、setXY()、setX()及setY();所以,这时候才会出现多个线程分别调用setX()及setY(),从而导致X和Y的值不一样!!!这就刚好验证了我上面那句“有待证实的话”!

最后,我想请大家一起讨论一下-----“线程一定不会跨实例运行吗?” 谢谢!!
czf825 2003-12-21
  • 打赏
  • 举报
回复
首先恭喜楼主PASS,我也准备年底考完!我想问问你做了多少模拟题?
关于你这道题我已经深入研究过了,答案的确为B!

下面是我的意见:
你所提供的例程之所以得不到TRUE结果,仅因为“st.setXY(2);”这句代码,意思就是说:i始终都是等于2,这时候,不管多少条线程运行,无论setXY()、setX()或setY()是否同步,X和Y的值都只会等于2,所以要想得到X和Y不相等的结果,必须让线程以不同的i值多运行几次,也就是多调用几次setXY()方法,每次都有不同的i值;再配合sleep()方法,这样,就很容易看到结果是“true”了!!

下面是我提供的例程一,通过编译,并且调试结果会出现"true"!!(修改你的原程序)

class SyncTest_57 { //147-57t
public int x;
public int y; //为了方便看到 X,Y的值,我把它改为了PUBLIC,不影响结果!

private synchronized void setX (int i) {
try{
Thread.sleep(500);//因为x=i时间太短,因此尽量延长运行时间
}catch(InterruptedException e){}
x=i;
}

private synchronized void setY (int i) {y=i;}

public void setXY(int i){setX(i); setY(i);}

public synchronized boolean check() {return x != y;}
}

class Test1 implements Runnable{
private SyncTest_57 st;

public Test1(SyncTest_57 st){
this.st=st;
}
public void run(){
while (true){
st.setXY((int)(Math.random()*100));//随机生成一个整数
if (st.check())
System.out.println("True!!"+"X="+st.x+" Y="+st.y);
else System.out.print('.'); //相同就打印'.'
}
} //end run();
} // end class Test1;

public class ThreadTest{
public static void main(String args[]){
SyncTest_57 st57=new SyncTest_57();

Test1 t1=new Test1(st57);
Thread thread1=new Thread(t1);
thread1.start();

Test1 t2=new Test1(st57);
Thread thread2=new Thread(t2);
thread2.start();

Test1 t3=new Test1(st57);
Thread thread3=new Thread(t3);
thread3.start();

Test1 t4=new Test1(st57);
Thread thread4=new Thread(t4);
thread4.start();

}
}

分析上面这条程序:调用setXY()方法与check()方法都在同一个run()里面,如果我们把这两个方法分开分别执行,那么同样也会得到"true"结果,而且还不需要用到sleep()方法。因此我们可以采用下面第二种方法进行调试:(此程序是 miwoo提供的)

class SharedVar{
private int x;
private int y;

public synchronized void setX (int i) {x=i;}
public synchronized void setY (int i) {y=i;}

public void setXY(int i){
setX(i);
setY(i);
}

public synchronized boolean check() {return x!=y;}
}

class a implements Runnable{
private SharedVar sv;
a(SharedVar sv){
this.sv=sv;
}

public void run(){
while(true){
sv.setXY((int)(Math.random()*100));
}
}
}


class b implements Runnable{
private SharedVar sv;
b(SharedVar sv){
this.sv=sv;
}

public void run(){
while(true){
if(sv.check())
System.out.println("\nx!=y: true");
else System.out.print(".");
}
}
}

public class SyncTest1{
public static void main(String[] args){
SharedVar sv=new SharedVar();

Thread a_thread1 = new Thread(new a(sv));
a_thread1.start();
Thread b_thread1 = new Thread(new b(sv));
b_thread1.start();
}
}

未完....
grgh2000 2003-12-20
  • 打赏
  • 举报
回复
本人写过测试,不知对不对,结果是启动了1000个THREAD,也不可能得到TRUE。
//SyncTest.java
public class SyncTest
{
private int x;
private int y;
private synchronized void setX (int i) {x=i;}
private synchronized void setY (int i) {y=i;}
public void setXY(int i)
{
setX(i);
setY(i);
}
public synchronized boolean check() {return x!=y;}
}
////////////////////////////////////////////////////////////////
//TestSync.java
public class TestSync extends Thread
{
SyncTest syncTest;
public TestSync(String name)
{
super(name);
syncTest = new SyncTest();
}

public static void main(String[] arg)
{
for(int i=0;i<1000;i++)
{
Thread ts = new TestSync("A"+i);
ts.start();
}
System.out.println("main is end!");

}

public void run()
{
for(int i=0;i<100;i++)
{
syncTest.setXY(i);
if(syncTest.check()) throw new RuntimeException("true!");
try {
Thread.sleep(1000);
}catch(Exception e)
{
throw new RuntimeException("interrupte!");
}
}
}
}
filippo1980 2003-12-16
  • 打赏
  • 举报
回复
努力
LJava 2003-12-13
  • 打赏
  • 举报
回复
To Talentz(华英才):
我认为某个线程执行(有系统调度)在调用SETXY时,setXY再调用setX和setY方法,因为setX和setY是同步的,这时该线程已经取得SyncTest_57对象的锁标志,所以其他线程还是不能修改X,Y的值!所以还是不能返回TRUE!你认为呢?如果你认为你说的对,请编一道例程说明你的观点好吗?
TO Jass: 没什么太多经验,考1.2 还是1.4也无所谓,差不多的!都是基础认证!你只要把SL_275这本书都看透,把147做会,多做题,就没问题!考试好过,重要的是学到东东!你说呢?
gudfen 2003-12-12
  • 打赏
  • 举报
回复
能与你交流吗?
联系方法
Jass 2003-12-12
  • 打赏
  • 举报
回复
兄弟考的是1.2还是1.4的亚?我也准备考SCJP,介绍点经验亚:)
nettman 2003-12-12
  • 打赏
  • 举报
回复
恭喜!
加载更多回复(7)

51,408

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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