有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为唯一对象实现可取消的线程管理器

我需要管理许多后台线程,这些线程使用一些对象作为键,但只有一个线程可以同时使用同一个对象,例如,当thread A正在处理object A时,如果thread B调用了object A来处理object A,那么thread A应该在thread B运行之前取消

这是我的代码,但当我运行时,第一个线程不会停止,而是继续执行第二个线程:

private static ExecutorService mExecutor = Executors.newCachedThreadPool();
private static ConcurrentMap<Object, Future> mRunningTasks = new ConcurrentHashMap<>();
public static void run(final Runnable runnable, final Object key) {
    Future<?> future = mRunningTasks.get(key);
    if (future != null) {
        future.cancel(true);
    }
    future = new FutureTask<>(new Runnable() {
        @Override
        public void run() {
            //How to handle InterruptedException here ?
            //while there's no potential to throw an InterruptedException
            runnable.run();
            mRunningTasks.remove(key);
        }
    }, null);
    mRunningTasks.put(key, future);
    mExecutor.execute((FutureTask) future);
}

我错过了什么

提前谢谢

PS: 当使用ImageView作为键对象取消请求时,我需要类似PicassoAPI的行为


共 (4) 个答案

  1. # 1 楼答案

    未来的文件。cancel()表示它试图取消任务,但可能不成功。您需要检查布尔返回值以查看它是否实际取消

  2. # 2 楼答案

    代码中还有多个其他条件

    ConcurrentHashMap是线程安全的,但您使用它的方式不是。 你可以: *多次取消未来 *添加未来而不取消上一个未来 *从地图中删除错误的未来

    你应该更具体地说明你实际上想要解决的问题。也许有更好的办法来解决这个问题

  3. # 3 楼答案

    这里有两个主要问题1)run方法需要声明为synchronized(在检查事物状态时避免争用条件)和2)future。cancel无法停止已开始的工作。因此,在runnables中添加您自己的防护/取消机制

    这就是说,最干净的解决方案是首先避免取消,但是在这个问题中没有足够的域细节来验证这是否可行。这类问题的一种常见模式是从运行中返回承诺并缓存承诺。承诺是异步操作结果的线程安全容器对象。如果同一工作安排两次,则可能会返回相同的承诺。如果一个承诺有一个值,则可以查看该值的使用年限来确定调度行为,例如返回旧值、返回旧值并在幕后计划更新该值,或者将旧值丢弃为太旧并获取干净的值

  4. # 4 楼答案

    您想杀死线程(Thread.stop()),这是一种非常糟糕的做法,由于许多原因被弃用。。。不仅因为线程由ThreadPool管理,所以您对线程没有责任,而且杀死它会破坏算法原子性的概念,使软件处于可能不确定的状态

    如果FutureTask尚未启动,您可以取消它。如果无法取消,则表示它已在运行。这在现代多核处理器上发生得非常快

    ThreadPool通常用于短期运行的线程。但是在您的情况下,正确结束任务的方法是在任务类中设置一个volatile boolean变量,并定期检查它以离开该方法

    InterruptedException仅在您的Thread正在等待或睡眠时才会抛出,而当前演示代码中不存在这种情况。如果您的Thread实际上正在等待或睡眠,则向监视器对象发送一个.notify()来中断它,并捕获try {} catch()中的Exception