【问题标题】:How I can replace deprecated method this.stop() in Thread [duplicate]如何替换线程中已弃用的方法 this.stop() [重复]
【发布时间】:2019-03-12 19:53:55
【问题描述】:

我正在从事 java 版本升级项目,并且我正在从事需要替换不推荐使用的方法的工作。

this.stop();

这个方法用到的代码在::

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) {
            }
        }
    }
}

我尝试对此进行大量搜索,但没有找到合适的解决方案,所以有没有人可以帮助我替换已弃用的 this.stop() 方法。

IDE 消息:ThreadGroup 类型的方法 stop() 已弃用

【问题讨论】:

  • 使用中断,不要忽略它们。
  • @GhostCat 该代码被用于 Junit 测试用例并且什么也没做,他们只是想确保所有线程都已关闭,因此我只是删除该行代码并运行它它工作得很好,我的意思是到目前为止所有的 Junit 测试用例都通过了,我认为我是好的一面。如果该代码用于主类或其他地方,我不会碰它。手指交叉,希望它不会在测试时产生任何错误。
  • 我能做到,但很抱歉你的回答给了我很多关于这个问题的想法,但不是确切的答案,所以我不能指出它是正确和具体的答案,非常感谢

标签: java multithreading java-8 thread-safety deprecated


【解决方案1】:

javadoc 对此非常清楚:

已弃用。这种方法本质上是不安全的。有关详细信息,请参阅 Thread.stop()。

在 Thread 的 javadoc 中,它一直在继续:

已弃用。这种方法本质上是不安全的。使用 Thread.stop 停止线程会导致它解锁所有已锁定的监视器(这是未检查的 ThreadDeath 异常在堆栈上传播的自然结果)。 ...

这里的问题:这既不是一个新问题,也不是一个“容易解决”的问题。

我的建议是如何处理这个问题:

  • 如果您真的关心此代码库,请将其丢弃。不要试图重构基于固有坏想法的东西。相反:评估您当前的需求,并设计一些新的东西来解决它们。
  • 如果您被告知“我们应该 修复已弃用的内容”,那么只需保持 原样。但是一定要花几个小时测试新设置中的现有代码。当事情仍然有效时,然后告诉提出此请求的人:“反射工作会非常昂贵,但似乎仍然有效。所以让我们继续使用它吧”。

换句话说:可能只做“最小”的改变来摆脱stop(),但改变是你必须投入大量时间。你看,多线程代码真的很难正确,更难正确测试。因此,很难预测“最小重构”的成本,因此,如前所述:考虑将其全部丢弃或保持原样。

【讨论】:

  • 我可以删除像这样的代码图片 public void interruptThenStop() { this.interrupt(); if(this.activeCount()>0) { this.stop(); //对于那些不会中断的线程 } } .实际上,他们已经在 this.interrupt() 的帮助下关闭了线程,如果在某些情况下,如果线程没有关闭,那么他们将在 this.stop() 的帮助下关闭线程,并且不推荐使用我搜索了很多但没有到达那里。
  • @PradipLamsal,您的interruptThenStop() 方法看起来可能是基于对this.interrupt() 所做的错误的想法。 this.interrupt() 呼叫不会等待任何事情。它可以在this 线程有机会响应中断之前返回。您没有向我们展示this.activeCount() 的作用,但如果它也无需等待任何东西就返回,那么我敢打赌this.stop() 被调用的频率比作者想象的要多更多调用。
  • @SolomonSlow this.activeCount() is method from Class ThreadGroup >>> ibb.co/xh6mSmL (Screenshot) 我不知道如何删除 this.stop() 方法:'(跨度>
  • @PradipLamsal,你错过了我的问题的重点:interruptThenStop() 方法调用activeCount() 来测试线程是否响应了中断。我问activeCount() 是否给线程 time 做出响应。这个名字听起来像一个“getter”的名字,这会让线程根本没有时间。我质疑interruptThenStop() 的作者是否知道他/她在做什么。如果模块需要调用stop(),那么这是一个糟糕的设计。架构错误没有简单的修复方法。我和 GhostCat 在一起:不要浪费时间试图修复它。重新开始。
猜你喜欢
  • 2012-10-02
  • 1970-01-01
  • 2021-06-25
  • 2018-03-30
  • 2015-06-25
  • 1970-01-01
  • 2013-05-08
  • 2013-11-23
  • 2013-10-15
相关资源
最近更新 更多