我已经写了一个简单的聊天服务器,但我不知道如何将消息发送到另一个线程。我尝试过的内容会返回错误:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
class ConnectorService extends Thread {
Socket connection;
ObjectInputStream in;
ObjectOutputStream out;
Thread _t;
public ConnectorService( Socket sock, ObjectInputStream _in, ObjectOutputStream _out ) {
this.connection = sock;
try {
in = _in;
out = _out;
out.flush( );
}
catch( Exception e ) {
System.err.println( "Wystapil blad laczenia do socketu.." );
}
}
@Override
public void run() {
this.send( "Siemka :P" );
while( true ) {
try {
String mess = (String)in.readObject( );
String[] m = mess.split( ":" );
if( m.length > 1 ) {
Thread _tmp;
if( ( _tmp = getThreadByName( m[ 0 ] ) ) != null ) {
// Here i've got an exception
( ( ConnectorService ) _tmp ).send( m[ 1 ] );
}
}
else {
System.err.println( "Zbyt malo argumentow.." );
}
this.getThreadByName( "test" );
System.out.println( "Klient: " + mess );
this.send( mess );
}
catch( ClassNotFoundException e ) {
System.err.println( "Bledny typ wiadomosci.." );
}
catch (IOException e) {
// e.printStackTrace();
System.err.println( "Polaczenie przerwane.." );
break;
}
}
}
public void start( ) {
System.out.println( "Uruchamiam klienta" );
if( _t == null ) {
_t = new Thread( this );
_t.start();
}
}
public void send( String message ) {
try {
out.writeObject( message );
out.flush();
}
catch( IOException e ) {
e.printStackTrace( );
}
}
public Thread getThreadByName(String threadName) {
for (Thread t : ConnectorService.getAllStackTraces().keySet()) {
if (t.getName().equals(threadName)) return t;
//System.out.println( t.getName() );
}
return null;
}
}
我试图投射一个我从方法getThreadByName()
获得的线程,但后来我收到了一个我无法投射线程的例外...
是否有可能在另一个线程中调用该方法? 问候
答案 0 :(得分:2)
有一大堆知识称为并发编程,似乎你必须从一开始就学习它。
您要做的是等待/通知(谷歌了)。你在对象的synchronized块中的一个线程中等待,然后其他线程调用通知同一个对象并且该线程被唤醒。您可以在该对象中放置消息以有效地传递它。
但这是进行并发编程的基本方法。你真正想要的是某种并发队列。在一个线程中发出阻塞读取,在另一个线程中将消息写入队列 - 第一个线程将解除阻塞并获取消息。 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
答案 1 :(得分:2)
就像alamar所说的那样,使用消息队列会更好,但由于你将它用于一个简单的程序,这是一个简单的解决方案:
您需要保留每个线程的引用列表,并保留每个线程的名称,可能使用地图:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
class ConnectorService extends Thread {
static Map<String, Thread> connectorServices = new HashMap<>();
Socket connection;
ObjectInputStream in;
ObjectOutputStream out;
Thread _t;
public ConnectorService(String name, Socket sock, ObjectInputStream _in, ObjectOutputStream _out) {
this.connection = sock;
try {
in = _in;
out = _out;
out.flush();
} catch (Exception e) {
System.err.println("Wystapil blad laczenia do socketu..");
}
// add this to the list of references to the threads
ConnectorService.connectorServices.put(name, this);
}
@Override
public void run() {
this.send("Siemka :P");
while (true) {
try {
String mess = (String) in.readObject();
String[] m = mess.split(":");
if (m.length > 1) {
Thread _tmp;
if ((_tmp = getThreadByName(m[0])) != null) {
// Here i've got an exception
((ConnectorService) _tmp).send(m[1]);
}
} else {
System.err.println("Zbyt malo argumentow..");
}
this.getThreadByName("test");
System.out.println("Klient: " + mess);
this.send(mess);
} catch (ClassNotFoundException e) {
System.err.println("Bledny typ wiadomosci..");
} catch (IOException e) {
// e.printStackTrace();
System.err.println("Polaczenie przerwane..");
break;
}
}
}
public void start() {
System.out.println("Uruchamiam klienta");
if (_t == null) {
_t = new Thread(this);
_t.start();
}
}
public void send(String message) {
try {
out.writeObject(message);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public Thread getThreadByName(String threadName) {
return ConnectorService.connectorServices.get(threadName);
}
}
此代码应该编译并正常工作......
但是请注意我没有使用适当的封装 - 我会把它留给你做...