Java runnable存储对其自身运行线程的引用时有任何注意事项吗?
我有一个长时间运行的可运行对象,我想提供一种比在对象运行的线程上调用中断更优雅的中断机制 前代码:Java runnable存储对其自身运行线程的引用时有任何注意事项吗?,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我有一个长时间运行的可运行对象,我想提供一种比在对象运行的线程上调用中断更优雅的中断机制 前代码: public class MyRunnable implements Runnable { public void run() { while(!Thread.currentThread().isInterrupted()) { //do stuff } } } public class MyClass { publ
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或原子布尔值来传达关闭意图,我更感兴趣的是学习而不是解决方案。但解决方案仍然是受欢迎的 它已经有了一个参考:
Thread.currentThread()
从:
返回对当前执行的线程对象的引用
对我来说,您的第一种方法更好,因为它不太容易出错,而且更“标准”。但实际上,您试图实现的已经存在(这证明它是有意义的,而且这不是一个坏的实践,但要正确地实现它并不容易),它被调用,而不是使用
true
作为maybruitrunning
的值关闭,如果您想中断运行任务的线程,我引用javadoc:
试图取消此任务的执行。如果
该任务已完成、已取消或可能无法执行
不能因为其他原因取消。如果成功,此任务
调用cancel时未启动,此任务不应运行。如果
任务已启动,则可能会中断fRunning
参数确定执行此任务的线程是否应
在试图停止任务时被中断
例如:
// 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 !!!
请注意,
isInterrupted
是一种方法,而不是field@NicolasFilotto只是一个输入错误,但你是绝对正确的。所以你的答案是Runnable存储对其执行线程的本地引用绝对没有任何警告/副作用,提供使用该线程的公共方法?我查看了FutureTask
源代码,它们确实存储了对当前正在执行的线程的内部引用,因此,至少如果我使用与它们类似的引用,我不应该期望它们没有记录的任何古怪行为。我接受了这个答案,尽管它更像是一个解决方案,而不是对我最初问题的回答。