对runnable的任何警告都存储对其自己的运行线程的引用?

时间:2016-10-28 15:24:55

标签: java multithreading thread-safety

我有一个长时间运行的Runnable对象,我想提供一个更优雅的中断机制,而不是在运行该对象的线程上调用中断。

之前的代码:

public class MyRunnable implements Runnable {
    public void run() {
        while(!Thread.currentThread().isInterrupted()) {
            //do stuff
        }
    }
}

public class MyClass {
    public static void main(String[] args) {
        Runnable myRunnable = new MyRunnable();
        Thread t = new Thread(myRunnable, "myRunnableThread");
        t.start();

        //do stuff

        t.interrupt();

        //do stuff
    }
}

新代码:

public class MyRunnable implements Runnable {
    private Thread myThread = null;
    public void run() {
        myThread = Thread.currentThread();
        while(!myThread.isInterrupted()) {
            //do stuff
        }
    }

    public void shutdown() {
        if (myThread != null) {
            myThread.interrupt();
            //do other shutdown stuff
        }
    }
}

public class MyClass {
    public static void main(String[] args) {
        Runnable myRunnable = new MyRunnable();
        Thread t = new Thread(myRunnable, "myRunnableThread");
        t.start();

        //do stuff

        myRunnable.shutdown();

        //do stuff
    }
}

我的问题是,是否存在可能导致对您自己的线程的引用的副作用或未知数,并通过公共方法(如上所述)提供对该线程的有限访问可能会导致?这假设没有人直接调用run()方法,它总是从新线程开始。

而且我知道我可以在run()shutdown()方法中使用volatile或atomic布尔值来传递关闭意图,我对学习比解决方案更感兴趣。但仍然欢迎解决方案!

2 个答案:

答案 0 :(得分:1)

对我来说,你的第一种方法要好得多,因为它不易出错,而且更符合标准"但实际上你试图实现的东西已经存在(这证明它是有意义的并且它不是一个坏习惯,但它并不容易使它正确),它被称为FutureTask,而不是关闭你有{{如果要中断运行任务的线程,true的值为mayInterruptIfRunning {3}},我引用javadoc:

  

尝试取消执行此任务。如果这种尝试失败了   任务已经完成,已经取消,或者可以   因其他原因不能取消。如果成功,那么这个任务   调用cancel时尚未启动,此任务永远不会运行。如果   任务已经开始,然后是mayInterruptIfRunning   参数确定执行此任务的线程是否应该是   因试图停止任务而中断。

例如:

// Task that will only sleep for 1 sec and print a message on interrupted
FutureTask<Void> myRunnable = new FutureTask<>(
    new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            try {
                System.out.println("Sleep");
                Thread.sleep(1_000L);
            } catch (InterruptedException e) {
                System.out.println("Interrupted !!!");
                throw e;
            }
            return null;
        }
    }
);
new Thread(myRunnable, "myRunnableThread").start();

// Wait long enough to make sure that myRunnableThread is sleeping 
Thread.sleep(500L);
// Cancel the task and interrupt myRunnableThread
myRunnable.cancel(true);

<强>输出:

Sleep
Interrupted !!!

答案 1 :(得分:0)

它已经有一个参考:

Thread.currentThread()

来自javadoc

  

返回对当前正在执行的线程对象的引用。