Read "Streaming Systems" 1&2, Streaming 101 Read "F1, a distributed SQL database that scales" Read "Zanzibar, Google’s Consistent, Global Authorization System" Read "Spanner, Google's Globally-Distributed Database" Read "Designing Data-intensive applications" 12, The Future of Data Systems IOS development with Swift Read "Designing Data-intensive applications" 10&11, Batch and Stream Processing Read "Designing Data-intensive applications" 9, Consistency and Consensus Read "Designing Data-intensive applications" 8, Distributed System Troubles Read "Designing Data-intensive applications" 7, Transactions Read "Designing Data-intensive applications" 6, Partitioning Read "Designing Data-intensive applications" 5, Replication Read "Designing Data-intensive applications" 3&4, Storage, Retrieval, Encoding Read "Designing Data-intensive applications" 1&2, Foundation of Data Systems Three cases of binary search TAMU Operating System 2 Memory Management TAMU Operating System 1 Introduction Overview in cloud computing 2 TAMU Operating System 7 Virtualization TAMU Operating System 6 File System TAMU Operating System 5 I/O and Disk Management TAMU Operating System 4 Synchronization TAMU Operating System 3 Concurrency and Threading TAMU Computer Networks 5 Data Link Layer TAMU Computer Networks 4 Network Layer TAMU Computer Networks 3 Transport Layer TAMU Computer Networks 2 Application Layer TAMU Computer Networks 1 Introduction Overview in distributed systems and cloud computing 1 A well-optimized Union-Find implementation, in Java A heap implementation supporting deletion TAMU Advanced Algorithms 3, Maximum Bandwidth Path (Dijkstra, MST, Linear) TAMU Advanced Algorithms 2, B+ tree and Segment Intersection TAMU Advanced Algorithms 1, BST, 2-3 Tree and Heap TAMU AI, Searching problems Factorization Machine and Field-aware Factorization Machine for CTR prediction TAMU Neural Network 10 Information-Theoretic Models TAMU Neural Network 9 Principal Component Analysis TAMU Neural Network 8 Neurodynamics TAMU Neural Network 7 Self-Organizing Maps TAMU Neural Network 6 Deep Learning Overview TAMU Neural Network 5 Radial-Basis Function Networks TAMU Neural Network 4 Multi-Layer Perceptrons TAMU Neural Network 3 Single-Layer Perceptrons Princeton Algorithms P1W6 Hash Tables & Symbol Table Applications Stanford ML 11 Application Example Photo OCR Stanford ML 10 Large Scale Machine Learning Stanford ML 9 Anomaly Detection and Recommender Systems Stanford ML 8 Clustering & Principal Component Analysis Princeton Algorithms P1W5 Balanced Search Trees TAMU Neural Network 2 Learning Processes TAMU Neural Network 1 Introduction Stanford ML 7 Support Vector Machine Stanford ML 6 Evaluate Algorithms Princeton Algorithms P1W4 Priority Queues and Symbol Tables Stanford ML 5 Neural Networks Learning Princeton Algorithms P1W3 Mergesort and Quicksort Stanford ML 4 Neural Networks Basics Princeton Algorithms P1W2 Stack and Queue, Basic Sorts Stanford ML 3 Classification Problems Stanford ML 2 Multivariate Regression and Normal Equation Princeton Algorithms P1W1 Union and Find Stanford ML 1 Introduction and Parameter Learning

How to safely stop threads in Java

2017-08-03

Introduction

Recently, I was involved in a project, in which several threads need to be stopped. However, the stop() in Thread class is deprecated. Here is an article published by Oracle stating why they think this method (and some related others) should not be used.

Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?

This article also provides safe alternative for those deprecated. Here I list some test code based on my understanding. Three cases are tested, as below.

  1. stopFlag method
  2. interrupt() method
  3. Multiple threads

Cases

stopFlag method

A volatile field called stopFlag is set to be false initially. The run() method of the Thread object keeps monitor this field. The stop() method will set stopFlag to be true. Then run() method will be stopped.

private static class ThreadTestSignal {
    private Thread thread;
    private volatile boolean stopFlag = false;

    public ThreadTestSignal() {
        thread = new Thread() {
            @Override
            public void run() {
                while (!stopFlag) {
                    System.out.println("working");
                }
            }
        };
    }

    public void start() {
        thread.start();
    }
    public void stop() {
        this.stopFlag = true;
    }
}

interrupt() method

The run() method of Thread object keeps monitor the value of currentThread.isInterrupted() or Thread.interrupted(). The stop() method will run currentThread.interrupt(). It has an advantage comparing with the stopFlag method. While the thread has a long sleep or wait, InterruptedException will be catched during sleep once interrupted, thus run() method will return and the thread will be stopped. But stopFlag method may need some time (due to sleep) to reach the stopFlag monitoring line.

private static class ThreadTestInterrupt {
     private Thread thread;

     public ThreadTestInterrupt() {
         thread = new Thread() {
             @Override
             public void run() {
                 while (!Thread.interrupted()) {
                     try {
                         Thread.sleep(300);
                     } catch (InterruptedException e) {
                         System.out.println("Interrupted");
                         return;
                     }
                     System.out.println("working");
                 }
             }
         };
     }

     public void start() {
         thread.start();
     }
     public void stop() {
         thread.interrupt();
     }
 }

Multiple threads

Actually, we don’t really need a boolean stopFlag. For the multiple threads case, a map (a set will be enough though) can be used. We put the thread ID for each thread in this map. It’s equivalent to maintain a boolean stopFlag for each thread. In stop() method, the map will be cleared, just like setting all stopFlags to be true.

private static class ThreadTestMultiSignal {
    private volatile ConcurrentMap<Integer, Integer> threadsMap;
    private static final int numThreads = 10;

    public ThreadTestMultiSignal() {
        threadsMap = new ConcurrentHashMap<>();
        for (int i = 0; i < numThreads; i++) {
            threadsMap.put(i, 0);
        }
        for (Integer noThread : threadsMap.keySet()) {
            new Thread() {
                @Override
                public void run() {
                    while (threadsMap.containsKey(noThread)) {
                        System.out.println("working thread: " + noThread);
                    }
                }
            }.start();
        }
    }

    public void stop() {
        threadsMap.clear();
    }
}

Main test code

The main function for test is as below.

public static void main(String[] args) {
    // For signal method
    System.out.println("Signal method, start");
    ThreadTestSignal testSignal = new ThreadTestSignal();
    testSignal.start();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        return;
    }
    testSignal.stop();
    System.out.println("Signal detected, stopped");

    // For interrupt method
    System.out.println("Interrupt method, start");
    ThreadTestInterrupt testInterrupt = new ThreadTestInterrupt();
    testInterrupt.start();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        return;
    }
    testInterrupt.stop();
    System.out.println("Thread interrupted, stopped");

    //For Multiple threads
    System.out.println("Multiple threads, start");
    ThreadTestMultiSignal testMultiSignal = new ThreadTestMultiSignal();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        return;
    }
    testMultiSignal.stop();
    System.out.println("Multiple signals detected, stopped");
}

Creative Commons License
Melon blog is created by melonskin. This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
© 2016-2019. All rights reserved by melonskin. Powered by Jekyll.