简体   繁体   English

Java在线程外访问对象

[英]Java access object outside thread

I want to access the instance created in t1 from outside the thread, is this possible?我想从线程外部访问在 t1 中创建的实例,这可能吗? So I can close the socket after the thread is executed.所以我可以在线程执行后关闭套接字。

Network class:网络类:

public class Network {

    Socket socket;

    public void changeConnection(String command)
    throws Exception { // Whatever exceptions might be thrown
        if (command.equals("connect")) {
            socket = new Socket(server, port);
        }
        else if (command.equals("disconnect")) {
            socket.close();
        }
    }
}

Main class:主要类:

public class Project1 {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Network network = new Network();
                    network.connect("connect");
                }
                catch (Exception ex) {

                }
        }
        });
        t1.start();
        Thread.sleep(20000);
        network.connect("disconnect");
    }
}

Yes, that's possible.是的,这是可能的。

In your code, the t1 variable is local to main(String[] args) :在您的代码中, t1变量是main(String[] args)本地变量:

public static void main(String[] args) {
    Thread t1 = ...
}

You cannot access local variables from outside the method where they are declared.您不能从声明它们的方法外部访问局部变量。 In order to do so, you just need to turn the local variable into a class member (also known as field or class property ).为此,您只需要将局部变量转换为类成员(也称为字段类属性)。 Then you can set the access modifier to define which classes can access it.然后你可以设置访问修饰符来定义哪些类可以访问它。

public class Project1 {

    protected static Thread t1;

    public static void main(String[] args) {
        t1 = new Thread...
    }
}

The t1 inside main() refers to the class member t1 . main()t1指的是类成员t1 Of course, because your main() method is static, you also need the class member you want to access from within main() to be static.当然,因为您的main()方法是静态的,您还需要您要从main()访问的类成员是静态的。 You can set the access modifier of t1 .您可以设置t1 的访问修饰符

Another way to do it另一种方法

But if you want to close the connection after the thread is executed, then why don't you just close it as the last statement of the thread?但是如果要在线程执行完后关闭连接,那为什么不直接作为线程的最后一条语句关闭呢?

public static void main(String[] args) throws Exception {
    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                Network network = new Network();
                network.changeConnection("connect");

                // Do loads of work...

                // All work has been done and we're done with the
                // connection. Why don't we close it just now?
                network.changeConnection("disconnect");
            }
            catch (Exception exc) {
                // Catch the exception properly
            }
        }
    });
    t1.start();
}

Or using a lambda expression:或者使用 lambda 表达式:

Thread t1 = new Thread(() -> {
    // body of run()
});
t1.start();

PS: You should always start class names (like Project1 ) with an uppercase character. PS:您应该始终以大写字符开头类名(如Project1 )。

Why you want to open the socket connection in new thread as a non-static object?为什么要在新线程中将套接字连接作为非静态对象打开? Because if you are opening the connection then certainly you want to close the connection.因为如果您要打开连接,那么您当然要关闭连接。
Now if you are opening it in a new thread and as non-static socket connection object then you have keep your main thread alive who is holding the object/handler of the your socket connection so that in the end you can close it, otherwise socket connection will never be closed and the resources and RAM area it had occupied will never be freed.现在,如果您在一个新线程中打开它并作为非静态套接字连接对象,那么您必须保持主线程处于活动状态,该线程持有套接字连接的对象/处理程序,以便最后您可以关闭它,否则为套接字连接永远不会关闭,它占用的资源和 RAM 区域永远不会被释放。

Disclaimer: Without understanding your complete requirement it is hard to give you a fitting solution but my speculative solutions for you are as below, choose which fits your case/requirement:免责声明:在不了解您的完整要求的情况下,很难为您提供合适的解决方案,但我为您提供的推测性解决方案如下,请选择适合您的情况/要求的解决方案:

One approach:一种方法:
Generally, database connections are opened as a static object so that it can be accessed by many threads and later be closed be some/last thread.通常,数据库连接作为静态对象打开,以便它可以被许多线程访问,然后在某个/最后一个线程中关闭。 So, you can create a your SocketConnection class and create a static java.net.Socket object, which will be used by all your threads, and once everything is done over that socket connection then your last thread will close the socket connection.因此,您可以创建一个SocketConnection类并创建一个静态java.net.Socket对象,该对象将被您的所有线程使用,一旦通过该套接字连接完成所有操作,您的最后一个线程将关闭该套接字连接。

Another approach (use java.lang.ThreadLocal):另一种方法(使用java.lang.ThreadLocal):
If you want to pass some information/object to other pieces of code without passing it in method parameters then ThreadLocal is your friend.如果您想将某些信息/对象传递给其他代码段而不将其传递到方法参数中,那么ThreadLocal是您的朋友。 It will help you pass the object to any portion of code which is being executed by same thread.它将帮助您将对象传递给由同一线程执行的任何代码部分。 ThreadLocal has thread scope , so now you can understand that anything you will put in ThreadLocal will be valid until that thread is alive. ThreadLocal 具有线程作用域,因此现在您可以理解,您将放入ThreadLocal任何内容都将有效,直到该线程处于活动状态。
Read this nice tutorial on how to use ThreadLocal .阅读有关如何使用 ThreadLocal 的精彩教程。

Another approach (solely based on the code example you used):另一种方法(仅基于您使用的代码示例):
I guess you are using Thread.sleep(20000);我猜你正在使用Thread.sleep(20000); so that by this sleep is over your thread t1 would have finished opening socket connection, and then you can do something, and at-last close socket connection.以便通过此睡眠结束您的线程t1将完成打开套接字连接,然后您可以执行某些操作,最后关闭套接字连接。
If that is the case, then using sleep() method like this is not recommended.如果是这种情况,则不建议使用像这样的 sleep() 方法。 So, after thread has started, you can check if it has finished execution, and if yes then you can do whatever you wish.因此,在线程启动后,您可以检查它是否已完成执行,如果是,则您可以为所欲为。 Below is code example:下面是代码示例:

    final Network network = new Network();
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Thread started...");
            try {
                network.changeConnection("connect");
            }
            catch (Exception ex) {

            }
    }
    });
    t1.start();
    System.out.println("Thread start command executed...");
    //Thread.sleep(20000);
    while(t1.isAlive()){
        //Do nothing...
    }
    network.changeConnection("disconnect");

As I think your problem, the solution should be like this.我认为你的问题,解决方案应该是这样的。 Main class:主要类:

public class project1 {

    static Thread t1 = null;

    public static void main(String[] args) throws Exception {

        t1 = new Thread(new Runnable() {

            public void run() {
                try {
                    network network = new network();
                    network.connect("connect");
                }
                catch (Exception ex) {

                }
            }
        });
        t1.start();
        Thread.sleep(20000);
        network.connect("disconnect");
    }
}

Now you can access it anywhere in Project1 class.现在您可以在 Project1 类中的任何位置访问它。

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

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