Can this reference in run() refer to Thread object when implementing Runnable?

830 views Asked by At

Sorry if the question is unclear

I am making a simple multithread program that has a linked list to store all thread created except the main thread. Then I want to send some signal to terminate the main thread but only when all other threads have closed and I intend to do this by making that when the thread close, it will remove itself from linked list then the main thread will check if that list size == null or not

here is my code

public class MainProgram {
    //some global static variable
    static List<Thread> threadList = new LinkedList<Thread>();
    public void main() throws IOException {
        ServerSocket serverSocket;
        serverSocket = new ServerSocket(1234);
        while(true){
            if(Shutdown_Handler.shutdown==true){
                //wait for all other thread close/terminate
                return
            }
            Socket s = serverSocket.accept();
            ClientThread x = new ClientThread(s);
            Thread y = new Thread(x);
            threadList.add(y);
            y.start();

        }
    }
}

when Shutdown_Handler.shutdown==true the main will check the threadList if it is null. The problem is I don't know how to make the thread remove itself from the list. As what I have searched, for normal object, I can create method like this

public class someObject {
    public static void delete(){
        if(list.size = null) return;
        list.remove(this);
    }
}

However, in case of thread, the Class implement Runnable so this reference is to the object but not the thread stored in the list

2

There are 2 answers

0
Michael Markidis On BEST ANSWER

I would recommend using a HashMap instead of a List. The keys can be the Thread Name (e.g. Thread.getName()) and the values will be the Threads.

Map<String, Thread> threadMap = new HashMap<String, Thread>();

You should also create this Map as a synchronizedMap (using Collections.synchronizedMap(...))

Map<String, Thread> synchronizedMap = Collections.synchronizedMap(threadMap);

Now, whenever you construct a Thread, you pass this HashMap into its constructor and the Thread can hold a reference to it. Therefore, when the Thread is about to terminate it can remove itself from the HashMap by using its own Thread name as the key to remove.

0
Stephen C On

Assuming that ClientThread is a Runnable, the basic code is:

public class ClientThread implements Runnable {
    public void run() {
        // do stuff
        MainProgram.threadList.remove(Thread.currentThread());
    }
}

However this has a couple of problems:

  1. There are going to be multiple threads performing operations on a list without proper synchronization. That is incorrect, and you are liable to get intermittent failures if you do this.

  2. Unless run() removes the thread from the list in a finally block, a thread that terminates abnormally is liable to not get removed.

  3. It is bad design to use a global static. And worse design to expose it as a bare (non-private) variable.

  4. A HashSet<Thread> would be more efficient if the number of threads is liable to be large.