0

I am working on java version upgrade project and I am on the work where I need to replace deprecated methods.

this.stop();

Code USed this method are in ::

ThreadedTestGroup.java::

    package utmj.threaded;

import junit.framework.*;
public class ThreadedTestGroup extends ThreadGroup {
    private Test test;
    private TestResult testResult;

    public ThreadedTestGroup(Test test) {
        super("ThreadedTestGroup");
        this.test = test;
    }


    public void interruptThenStop() {
        this.interrupt();
        if (this.activeCount() > 0) {
        this.stop(); // For those threads which won't interrupt
        }
    }


    public void setTestResult(TestResult result) {
        testResult = result;
    }


    public void uncaughtException(Thread t, Throwable e) {
        if (e instanceof ThreadDeath) {
            return;
        }
        if (e instanceof AssertionFailedError) {
            testResult.addFailure(test, (AssertionFailedError) e);
        } else {
            testResult.addError(test, e);
        }
        this.interruptThenStop();
    }
}

ConcurrentTestCase.java

    package utmj.threaded;

import java.util.*;

import junit.framework.*;

/
public class ConcurrentTestCase extends TestCase {
    private TestResult currentResult;
    private ThreadedTestGroup threadGroup;
    private Hashtable threads = new Hashtable();
    private boolean deadlockDetected = false;
    private Vector checkpoints = new Vector();

    class ConcurrentTestThread extends Thread {
        private volatile boolean hasStarted = false;
        private volatile boolean hasFinished = false;
        ConcurrentTestThread(
            ThreadGroup group,
            Runnable runnable,
            String name) {
            super(group, runnable, name);
        }
        public void run() {
            hasStarted = true;
            super.run();
            finishThread(this);
        }
    }

    public ConcurrentTestCase(String name) {
        super(name);
    }

    public ConcurrentTestCase() {
        super();
    }

    protected void addThread(String name, final Runnable runnable) {
        if (threads.get(name) != null) {
            fail("Thread with name '" + name + "' already exists");
        }
        ConcurrentTestThread newThread =
            new ConcurrentTestThread(threadGroup, runnable, name);
        threads.put(name, newThread);
    }

    public synchronized void checkpoint(String checkpointName) {
        checkpoints.addElement(checkpointName);
        this.notifyAll();
    }

    public boolean checkpointReached(String checkpointName) {
        return checkpoints.contains(checkpointName);
    }

    public boolean deadlockDetected() {
        return deadlockDetected;
    }

    private synchronized void finishThread(ConcurrentTestThread thread) {
        thread.hasFinished = true;
        this.notifyAll();
    }

    private ConcurrentTestThread getThread(String threadName) {
        return (ConcurrentTestThread) threads.get(threadName);
    }

    /**
     * Returns true if the thread finished normally, i.e. was not inerrupted or stopped
     */
    public boolean hasThreadFinished(String threadName) {
        ConcurrentTestThread thread = this.getThread(threadName);
        if (thread == null) {
            fail("Unknown Thread: " + threadName);
        }
        return thread.hasFinished;
    }

    public boolean hasThreadStarted(String threadName) {
        ConcurrentTestThread thread = this.getThread(threadName);
        if (thread == null) {
            fail("Unknown Thread: " + threadName);
        }
        return thread.hasStarted;
    }

    private void interruptAllAliveThreads() {
        threadGroup.interruptThenStop();
    }

    /**
     * Wait till all threads have finished. Wait maximally millisecondsToWait.
     * Should only be called after startThreads().
     */
    protected void joinAllThreads(long millisecondsToWait) {
        Enumeration enum1 = threads.elements();
        long remainingMilliseconds = millisecondsToWait;
        while (enum1.hasMoreElements()) {
            long before = System.currentTimeMillis();
            ConcurrentTestThread each =
                (ConcurrentTestThread) enum1.nextElement();
            try {
                each.join(remainingMilliseconds);
            } catch (InterruptedException ignored) {
            }
            long spent = System.currentTimeMillis() - before;
            if (millisecondsToWait != 0) {
                remainingMilliseconds = remainingMilliseconds - spent;
                if (remainingMilliseconds <= 0) {
                    deadlockDetected = true;
                    break;
                }
            }
        }
    }

    public void joinThread(String threadName) throws InterruptedException {
        this.joinThread(threadName, 0);
    }

    public void joinThread(String threadName, long millisecondsToTimeout)
        throws InterruptedException {
        ConcurrentTestThread thread = this.getThread(threadName);
        if (thread == null) {
            fail("Unknown Thread: " + threadName);
        }
        thread.join(millisecondsToTimeout);
    }

    /**
     * Stores the current result to be accessible during the test
     */
    public void run(TestResult result) {
        currentResult = result;
        super.run(result);
    }

    protected void setUp() throws Exception {
        threadGroup = new ThreadedTestGroup(this);
    }

    /**
     * Sleep and ignore interruption
     */
    public void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException ignored) {
        }
    }

    /**
     * Run all threads and wait for them to finish without timeout
     */
    protected void startAndJoinAllThreads() {
        this.startAndJoinThreads(0);
    }


    protected void startThreads() {
        threadGroup.setTestResult(currentResult);
        Enumeration enum1 = threads.elements();
        while (enum1.hasMoreElements()) {
            ConcurrentTestThread each =
                (ConcurrentTestThread) enum1.nextElement();
            each.start();
            each.hasStarted = true;
        }
        Thread.yield();
    }



    protected void tearDown() throws Exception {
            this.interruptAllAliveThreads();
            threads = new Hashtable();
            checkpoints = new Vector();
            deadlockDetected = false;
            threadGroup = null;
            currentResult = null;
        }

    public synchronized void waitForCheckpoint(String checkpointName) {
        while (!this.checkpointReached(checkpointName)) {
            try {
                this.wait();
            } catch (InterruptedException ignored) {
            }
        }
    }


    public synchronized void waitUntilFinished(String threadName) {
        while (!this.hasThreadFinished(threadName)) {
            try {
                this.wait();
            } catch (InterruptedException ignored) {
            }
        }
    }
}

I tried to search lot about this but did not got suitable solution so is there anyone who can help me out to replace this.stop() method which is deprecated.

IDE message: The method stop() from the type ThreadGroup is deprecated

James Bond
  • 51
  • 1
  • 8
  • 3
    Use interruptions and don't ignore them. – shmosel Mar 12 '19 at 19:57
  • @GhostCat that code was used into the Junit test case and did nothing much, they are just want to make sure all threads are closed and because of that I just remove that line of code and run it and it works fine, I mean all Junit test cases are passed so far I am thinking I am in good side. If that code is used in main class or in somewhere else I will not touch that. Finger crossed, hope it is not gonna create any errors at testing time. – James Bond Mar 14 '19 at 13:21
  • I can do that but sorry to say your answer give me lots of ideas about the question but not the exact answer so I cannot point it as correct and specific answer in my case, really appreciated – James Bond Mar 14 '19 at 14:53

1 Answers1

1

The javadoc is pretty clear about this:

Deprecated. This method is inherently unsafe. See Thread.stop() for details.

And in the javadoc for Thread, it goes on and on:

Deprecated. This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). ...

The problem here: this is neither a new nor an "easy to solve" problem.

My recommendation how to approach this:

  • if you really care about this code base, then throw it away. Don't try to refactor something that was build on inherently bad ideas. Instead: evaluate your current requirements, and design something new that addresses them.
  • if you were told "we should fix deprecated stuff", then simply keep things as they are. But do spend some hours testing that existing code in your new setup. When things still work, then tell the person who made this request: "that reflection work would be really really expensive, but it seems things are still working. so let's just keep using it".

In other words: it might be possible to just do "minimal" changes to get rid of stop(), but changes are that you have to invest a lot of time. And you see, multi threaded code is really hard to get right, and even harder to properly test. Therefore it is hard to predict the cost of a "minimal refactoring", thus, as said: consider throwing it all away or keeping it as is.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • can I just remove that pic of code which is like this public void interruptThenStop() { this.interrupt(); if(this.activeCount()>0) { this.stop(); //For those threads which won't interrupt } } . Actually they are already closing the thread with the help of this.interrupt() and if insome case if the threads are not closed then they are closing that with the help of this.stop() and which is deprecated I searched a lot but not getting there. – James Bond Mar 12 '19 at 20:12
  • @PradipLamsal, Your `interruptThenStop()` method looks like it might be based on a wrong idea about what `this.interrupt()` does. The `this.interrupt()` call does not wait for anything. It can return _before_ the `this` thread has any chance to respond to the interrupt. You did not show us what `this.activeCount()` does, but if it also returns without waiting for anything, then I'll wager that `this.stop()` is being called _much_ more often than the author thought it would be called. – Solomon Slow Mar 12 '19 at 21:53
  • @SolomonSlow this.activeCount() is method from Class ThreadGroup >>> https://ibb.co/xh6mSmL (Screenshot) I don't know how I can remove that this.stop() method :'( – James Bond Mar 13 '19 at 00:09
  • @PradipLamsal, You miss the point of my question: The `interruptThenStop()` method calls `activeCount()` to test whether the thread has responded to the interrupt. I asked whether `activeCount()` gives the thread _time_ in which to respond. The name sounds like the name of a "getter", that would give the thread no time at all. I question whether the author of `interruptThenStop()` knew what he/she was doing. If the module _needs_ the `stop()` call, then it's a bad design. There are no simple fixes for architectural mistakes. I'm with GhostCat: Don't waste time trying to fix it. Start over. – Solomon Slow Mar 13 '19 at 13:35