问题描述
代码功能:客户端输入三个整数,服务器端返回客户端这三个整数的和我的思路服务器端起两个线程,一个监听,一个向客户端写出数据的线程,当收到数据后,用notify()唤醒写出线程,但我下面的代码输出端一直wait在那里,notify()都没用,不能实现同步啊publicclassServer{/**Server*/publicstaticfinalintPORT=6666;privateServerSocketserver=null;privateSocketclient=null;privateinta,b,c;privatebooleanflag=false;publicServer(){}publicvoidbegin(){try{server=newServerSocket(PORT);System.out.println("Server:serverstarting...");client=server.accept();System.out.println("Server:aclientconnect!");newThread(newReadThread()).start();newThread(newWriteThread()).start();}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}classReadThreadimplementsRunnable{@Overridepublicvoidrun(){synchronized(this){try{DataInputStreamdis=newDataInputStream(client.getInputStream());while(true){a=dis.readInt();b=dis.readInt();c=dis.readInt();System.out.println("Server:"+a+","+b+","+c);flag=true;notify();}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}classWriteThreadimplementsRunnable{@Overridepublicvoidrun(){synchronized(this){try{DataOutputStreamdos=newDataOutputStream(client.getOutputStream());while(true){if(!flag){try{wait();System.out.println("Server:wakeup");}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}dos.writeInt(a+b+c);dos.flush();//dos.close();flag=false;}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}publicstaticvoidmain(String[]args){newServer().begin();}}
客户端publicclassClient{/**Client*/privateSocketclient=null;publicvoidbegin(){try{client=newSocket("127.0.0.1",Server.PORT);System.out.println("Client:connecttoserver!");newThread(newReadThread()).start();newThread(newWriteThread()).start();}catch(UnknownHostExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}classReadThreadimplementsRunnable{@Overridepublicvoidrun(){try{DataInputStreamdis=newDataInputStream(client.getInputStream());while(true){intn=dis.readInt();System.out.println("Client:"+n);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}classWriteThreadimplementsRunnable{@Overridepublicvoidrun(){try{DataOutputStreamdos=newDataOutputStream(client.getOutputStream());Scannersc=newScanner(System.in);while(true){System.out.print("输入a:");inta=sc.nextInt();System.out.print("输入b:");intb=sc.nextInt();System.out.print("输入c:");intc=sc.nextInt();dos.writeInt(a);dos.writeInt(b);dos.writeInt(c);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}publicstaticvoidmain(String[]args){newClient().begin();}}
求大侠指教
解决方案
解决方案二:
你的服务端ReadThread和WriteThread的run方法整体用this同步,当其中一个获得锁的时候,另外一个线程永远获得不了锁。即使你调用notify.因为同步块代码没有执行完,所以锁没有释放。可以改成同步只对wait和write起作用
解决方案三:
也就是同步去掉,改为在42行和64行加上同步
解决方案四:
改了之后的服务端代码,才看见你的服务端同步代码锁是this.。。。。你需要好好考虑下this啥意思publicclassTestSocketClient{/**Client*/privateSocketclient=null;publicvoidbegin(){try{client=newSocket("127.0.0.1",6666);System.out.println("Client:connecttoserver!");newThread(newReadThread()).start();newThread(newWriteThread()).start();}catch(UnknownHostExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}classReadThreadimplementsRunnable{@Overridepublicvoidrun(){try{DataInputStreamdis=newDataInputStream(client.getInputStream());while(true){intn=dis.readInt();System.out.println("Client:"+n);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}classWriteThreadimplementsRunnable{@Overridepublicvoidrun(){try{DataOutputStreamdos=newDataOutputStream(client.getOutputStream());Scannersc=newScanner(System.in);while(true){System.out.print("输入a:");inta=sc.nextInt();System.out.print("输入b:");intb=sc.nextInt();System.out.print("输入c:");intc=sc.nextInt();dos.writeInt(a);dos.writeInt(b);dos.writeInt(c);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}publicstaticvoidmain(String[]args){newTestSocketClient().begin();}}
解决方案五:
。。。需要同步的是两个是内部类,所以要实现两个不同类对象的同步,怎么搞
解决方案六:
引用4楼u013351347的回复:
。。。需要同步的是两个是内部类,所以要实现两个不同类对象的同步,怎么搞
内部类可以访问外部类的变量,这有什么问题,并且我代码都给你写出来了
解决方案七:
。。。。你给的是客户端,请给我一下服务器端
解决方案八:
按照楼主的思路可以很简单的完成,你的wait与notify没有用的。read和write是两个独立的线程,没有任何公共资源,wait后是不能被唤醒。楼主可以去看看生产者消费者的例子。了解一下wait与notify的用法。wait与notify方法是object类的,根据楼主的意思,我用了两个线程来完成,楼主可以参考下。/****/packagecom.ball.thread;importjava.io.DataInputStream;importjava.io.DataOutputStream;importjava.io.IOException;importjava.net.Socket;importjava.net.UnknownHostException;importjava.util.Scanner;/***@authoradmin**/publicclassWriteThreadimplementsRunnable{Socketsocket;booleanflag=true;publicvoidrun(){try{socket=newSocket("127.0.0.1",8421);}catch(UnknownHostExceptione1){//TODOAuto-generatedcatchblocke1.printStackTrace();}catch(IOExceptione1){//TODOAuto-generatedcatchblocke1.printStackTrace();}try{DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());DataInputStreamdis=newDataInputStream(socket.getInputStream());Scannersc=newScanner(System.in);while(flag){System.out.print("输入a:");inta=sc.nextInt();System.out.print("输入b:");intb=sc.nextInt();System.out.print("输入c:");intc=sc.nextInt();dos.writeInt(a);dos.writeInt(b);dos.writeInt(c);inti=dis.readInt();System.out.println(i);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}
/****/packagecom.ball.thread;importjava.io.DataInputStream;importjava.io.DataOutputStream;importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;/***@authoradmin**/publicclassReadThreadimplementsRunnable{publicvoidrun(){ServerSocketss;Socketsocket=null;try{ss=newServerSocket(8421);socket=ss.accept();}catch(IOExceptione1){//TODOAuto-generatedcatchblocke1.printStackTrace();}try{DataInputStreamdis=newDataInputStream(socket.getInputStream());DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());while(true){inta=dis.readInt();intb=dis.readInt();intc=dis.readInt();System.out.println("Server:"+a+","+b+","+c);intsum=a+b+c;dos.writeInt(sum);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}
/****/packagecom.ball.thread;importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;/***@authoradmin**/publicclassTest{publicstaticvoidmain(String[]args){Threadthread1=newThread(newWriteThread());thread1.start();Threadthread2=newThread(newReadThread());thread2.start();}}
解决方案九:
按照楼主的思路,又重新写了一下代码。服务端:公共类:/****/packagecom.ball.thread;/***@authoradmin**/publicclassCommon{privateinta;privateintb;privateintc;/***@returnthea*/publicintgetA(){returna;}/***@paramatheatoset*/publicvoidsetA(inta){this.a=a;}/***@returntheb*/publicintgetB(){returnb;}/***@parambthebtoset*/publicvoidsetB(intb){this.b=b;}/***@returnthec*/publicintgetC(){returnc;}/***@paramcthectoset*/publicvoidsetC(intc){this.c=c;}privatebooleanflag=false;publicsynchronizedvoidsetNum(inta,intb,intc){if(flag){try{super.wait();}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}this.setA(a);this.setB(b);this.setC(c);flag=true;super.notify();}publicsynchronizedintadd(){intcount=0;if(!flag){try{super.wait();}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}count=this.getA()+this.getB()+this.getC();flag=false;super.notify();returncount;}}
读线程:/****/packagecom.ball.thread;importjava.io.DataInputStream;importjava.io.DataOutputStream;importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;/***@authoradmin**/publicclassReadThreadimplementsRunnable{privateCommoncommon;Socketsocket;publicReadThread(Socketsocket,Commoncommon){this.common=common;this.socket=socket;}publicvoidrun(){try{DataInputStreamdis=newDataInputStream(socket.getInputStream());DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());while(true){inta=dis.readInt();intb=dis.readInt();intc=dis.readInt();System.out.println("Server:"+a+","+b+","+c);common.setNum(a,b,c);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}
加法:/****/packagecom.ball.thread;importjava.io.DataOutputStream;importjava.io.IOException;importjava.net.Socket;/***@authoradmin**/publicclassAddThreadimplementsRunnable{privateCommoncommon;privateSocketsocket;publicAddThread(Socketsocket,Commoncommon){this.common=common;this.socket=socket;}publicvoidrun(){while(true){intsum=common.add();try{DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());dos.writeInt(sum);}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}
客户端:/****/packagecom.ball.thread;importjava.io.DataInputStream;importjava.io.DataOutputStream;importjava.io.IOException;importjava.net.Socket;importjava.net.UnknownHostException;importjava.util.Scanner;/***@authoradmin**/publicclassWriteThreadimplementsRunnable{publicstaticvoidmain(String[]args){Threadthread1=newThread(newWriteThread());thread1.start();}Socketsocket;booleanflag=true;publicvoidrun(){try{socket=newSocket("127.0.0.1",8421);}catch(UnknownHostExceptione1){//TODOAuto-generatedcatchblocke1.printStackTrace();}catch(IOExceptione1){//TODOAuto-generatedcatchblocke1.printStackTrace();}try{DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());DataInputStreamdis=newDataInputStream(socket.getInputStream());Scannersc=newScanner(System.in);while(flag){System.out.print("输入a:");inta=sc.nextInt();System.out.print("输入b:");intb=sc.nextInt();System.out.print("输入c:");intc=sc.nextInt();dos.writeInt(a);dos.writeInt(b);dos.writeInt(c);inti=dis.readInt();System.out.println(i);}}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}
测试:/****/packagecom.ball.thread;importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;/***@authoradmin**/publicclassTest{publicstaticvoidmain(String[]args){Commoncommon=newCommon();ServerSocketss;Socketsocket=null;try{ss=newServerSocket(8421);socket=ss.accept();}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}Threadthread1=newThread(newReadThread(socket,common));thread1.start();Threadthread2=newThread(newAddThread(socket,common));thread2.start();}}
解决方案十:
太感谢了。那天我问我老师,他说服务器端没必要起2个线程来监控读和写,最好写在一起
解决方案十一:
恩,这种问题可以不必写wait与notify,按我第一个就能完成。楼主如果有兴趣可以看看生产者与消费者的例子,那里用到可wait与notify
解决方案十二:
加一个异步吧synchronized(A.thread){A.thread.notify();}