简体   繁体   English

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

[英]Calling a method from another thread in java

I've written a simple chat server, but i don't have an idea how to send message to another thread. 我已经编写了一个简单的聊天服务器,但是我不知道如何将消息发送到另一个线程。 What i've tried returns an error: 我尝试过的返回错误:

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;
}

}

I've tried to cast a thread that i get from method getThreadByName() , but then i've received an exception that i cannot cast a thread.. 我试图转换一个从方法getThreadByName()获得的线程,但是随后我收到了一个我不能转换线程的异常。

Is the any possibility to call that method in another thread? 有可能在另一个线程中调用该方法吗? Greetings 问候

There's a huge blob of knowledge called concurrent programming and it seems that you have to learn it from the start. 有大量的知识称为并发编程,似乎您必须从一开始就学习它。

What you are trying to do is wait/notify (google it up). 您要尝试的是等待/通知(将其谷歌搜索)。 You wait in one thread in synchronized block on object, then other thread calls notify on the same object and that thread wakes up. 您在对象上的同步块中的一个线程中等待,然后其他线程调用在同一对象上通知,该线程唤醒。 You can probably put message in that object to effectively pass it. 您可能可以将消息放在该对象中以有效地传递它。

But it's a rudimentary way to do concurrent programming. 但这是进行并行编程的基本方法。 What you really want here is some kind of concurrent queue. 您真正想要的是某种并发队列。 Issue blocking read in one thread, write message to queue in another - first thread will un-block and get the message. 发出阻塞阻止在一个线程中读取,将消息写入另一个队列中的事务-第一个线程将解除阻塞并获取消息。 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

Like alamar said, using a message queue would be better, but since you are using this for a simple program, here's a simple solution: 就像alamar所说的那样,使用消息队列会更好,但是由于您将它用于简单的程序,因此这是一个简单的解决方案:

You need to keep a list of references to each thread you make, and also keep the name of each thread, maybe using a map: 您需要保留对所创建的每个线程的引用的列表,还需要保留每个线程的名称(可能使用映射):

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

This code should compile and work fine... 该代码应可以编译并正常工作。

BUT notice how I did not use proper encapsulation - I'll leave that up to you to do... 但是请注意我是如何使用不正确的封装的-我将由您自己决定...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM