从java中的另一个线程调用方法

时间:2015-11-18 23:40:17

标签: java multithreading sockets

我已经写了一个简单的聊天服务器,但我不知道如何将消息发送到另一个线程。我尝试过的内容会返回错误:

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()获得的线程,但后来我收到了一个我无法投射线程的例外...

是否有可能在另一个线程中调用该方法? 问候

2 个答案:

答案 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);
    }
}

此代码应该编译并正常工作......

但是请注意我没有使用适当的封装 - 我会把它留给你做...