Home > Software engineering >  How to send variable between classes while multithreading
How to send variable between classes while multithreading

Time:06-30

This a much simplified version of my multithreading project and its just a way to replicate the issue in a simpler way for easy understanding.

So I have two classes startSession.java and main.java

what I am trying to do is to send a variable from startSession.java to main.java and Im also using multithreading. However, the problem I am facing is that everytime I try to retrieve the variable inside main I get a null value.

Inside startSession theres the run method and Setter(setSessionKey(String sess)) and getter(getSessionKey()) methods. I hardcoded a variable to test.

The get method only works inside the run method but when I call getSessionKey() from inside main I get a null as seen below. However, this is only a problem when I am using multithreading. When I dont use multithreading and instead just call the run method from inside main, the variable Im looking for is no longer null.

My question is there a way to send a variable from startSession to main while using multithreading ?

thank you

startSession.java

public class startSession extends Thread {

    static String sessionKey;

    public void run() {
        String createdSession = "83248329";
        setSessionKey(createdSession);
        System.out.println("Inside run method: "   getSessionKey());
    }

    public String getSessionKey() {
        return sessionKey;
    }

    public void setSessionKey(String sess) {
        sessionKey = sess;
    }
}

main.java

package com.Server;

public class Main {

    static String session;

    public static void main(String[] args) throws InterruptedException {
        startSession startSession = new startSession();

        startSession.start();

        session = startSession.getSessionKey();
        System.out.println("Inside Main: "   session);
    }
}

with multithreading

enter image description here

without multithreading

enter image description here

CodePudding user response:

Use Callback to get sessionKey:

public class startSession extends Thread  {

    static String sessionKey;


    SessionKeyCallBack sessionKeyCallBack;
    public startSession()
    {
        getSessionKey();
    }

    public void setSessionKeyCallBack(SessionKeyCallBack sessionKeyCallBack) {
        this.sessionKeyCallBack = sessionKeyCallBack;
    }

    public void run(){

        String createdSession= "83248329";
        setSessionKey(createdSession);
        System.out.println("Inside run method: "  getSessionKey());
        if (sessionKeyCallBack != null) {
            sessionKeyCallBack.onSetSessionKey(sessionKey);
        }
    }

    public String getSessionKey() {
        return sessionKey;
    }

    public  void setSessionKey(String sess) {
        sessionKey = sess;
    }

    interface SessionKeyCallBack {
        void onSetSessionKey(String sessionKey);
    }
}

you will get sessionKey on callback:

public class Main {
    static String session;

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

        startSession startSession= new startSession();
        startSession.setSessionKeyCallBack(new startSession.SessionKeyCallBack() {
            @Override
            public void onSetSessionKey(String sessionKey) {

                System.out.println("Inside Main: " sessionKey);
            }
        });

        startSession.start();
    }
}

CodePudding user response:

Use a BlockingQueue whereby the Thread (Producer) will add to the shared queue and the Main (Consumer) will block on the take

main

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

    BlockingQueue queue = new ArrayBlockingQueue(1024);

    StartSession producer = new StartSession(queue);

    ....
    System.out.println(queue.take());

startSession

   String createdSession= "83248329";
   queue.add(createdSession);

see https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

and https://jenkov.com/tutorials/java-util-concurrent/blockingqueue.html

CodePudding user response:

The easiest answer is: The thread has not initialized the session yet.

When I run your pasted code this is also the true one. I modified your example code so it works correctly. Please bear in mind that in a real world implementation you should not do it with one sleep but either via a callback or some waiting / timeout mechanism.

import java.lang.Thread;

public class Main {
    static String session;

    public static void main(String[] args) throws InterruptedException {
    Main m = new Main();
    }
    
    public Main() {
        StartSession startSession = new StartSession();
        startSession.start();
        // not working because the thread has not assigned the session yet
        session = startSession.getSessionKey();
        System.out.println("Inside Main 1: "   session);
        // let the main thread sleep for a second for the startSession to catch up
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // do nothing
        }
        // working because the thread had enough time to assign the session
        session = startSession.getSessionKey();
        System.out.println("Inside Main 2: "   session);
    }

    public class StartSession extends Thread  {
        // I strongly recommend to use the volatile modifier, see https://stackoverflow.com/questions/2423622/volatile-vs-static-in-java
        volatile static String sessionKey;
        
        public void run() {
            String createdSession= "83248329";
            setSessionKey(createdSession);
            System.out.println("Inside run method: "  getSessionKey());
            System.out.println("Thread run finished... ");
        }

        public String getSessionKey() {
            return sessionKey;
        }

        public void setSessionKey(String sess) {
            sessionKey = sess;
        }
    }
}

Also please do add the volatile modifier to your static variable otherwise you may encounter problems very hard to understand (in my code there is a comment linking to an explanation).

  • Related