有办法阻止线程调用 notify()
/notifyAll()
吗?
然后,就可以在类内部调用notify
。
一种notify
的私有(private)方法。 (一种,我们知道,我们不能)
这里有一些代码,必须注意synchronized
中的OtherThread
,这是我想要阻止的:
public class MainThread {
public static void main (String[] args) throws InterruptedException{
Thread.currentThread().setName("Main Thread");
X x = new X();
x.start();
OtherThread y = new OtherThread(x);
y.start();
synchronized (x){
System.out.println(Thread.currentThread().getName()+" Waiting");
x.wait();
}
System.out.println(Thread.currentThread().getName()+": Now I'm running");
}
}
class X extends Thread{
public void run(){
// setting thread name
Thread.currentThread().setName("X");
try {
Thread.sleep(1000*5); // 5 seconds here
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this){
this.notify();// I want only notify/notifyAll inside X to be possible
System.out.println("Notified from "+Thread.currentThread().getName()+" Thread");
}
}
}
class OtherThread extends Thread{
Thread t;
public OtherThread(Thread x){ // pass the X thread to this thread
this.t = x;
}
public void run(){
// setting thread name
Thread.currentThread().setName("OtherThread");
try {
Thread.sleep(1000*1); // 1 second here
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (t){
t.notify(); // prevent this. To can't call notify from outside class X.
System.out.println("Notified from "+Thread.currentThread().getName()+" Thread");
}
}
}
最佳答案
嗯,答案是你不能。我的意思是,您根本无法更改 notify
/wait
可见性(它们对所有对象都设置为公共(public))
但是,我认为可见性并不是适合您的工具。您正在使用 X 的实例作为您正在等待/通知的监视器。问题是,由于其他未指定的原因,您也将该 X 线程共享给其他线程。因此每个人都可以潜在地调用 wait/notify。
我的建议是使用另一个对象作为监视器(而不是 X 的实例)并仅在需要与其交互的对象之间共享该对象。像这样的东西:
public class MainThread {
public static void main (String[] args) throws InterruptedException{
Thread.currentThread().setName("Main Thread");
Object monitor = new Object();
X x = new X(monitor);
x.start();
OtherThread y = new OtherThread(x);
y.start();
synchronized (monitor){
System.out.println(Thread.currentThread().getName()+" Waiting");
monitor.wait();
}
System.out.println(Thread.currentThread().getName()+": Now I'm running");
}
}
class X extends Thread{
private Object monitor;
public X(Object monitor) {
this.monitor = monitor;
}
public void run(){
// setting thread name
Thread.currentThread().setName("X");
try {
Thread.sleep(1000*5); // 5 seconds here
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this.monitor){
this.monitor.notify();// I want only notify/notifyAll inside X to be possible
System.out.println("Notified from "+Thread.currentThread().getName()+" Thread");
}
}
}
class OtherThread extends Thread{
Thread t;
public OtherThread(Thread x){ // pass the X thread to this thread
this.t = x;
}
public void run(){
// setting thread name
Thread.currentThread().setName("OtherThread");
try {
Thread.sleep(1000*1); // 1 second here
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (t){
t.notify(); // this will work, but it wont do anything.
System.out.println("Notified from "+Thread.currentThread().getName()+" Thread");
}
}
}
此外,只有一个优点,我建议您查看更高级的方法来同步它。您可以创建一个 Semaphore
(或 CountDownLatch
),而不是仅仅共享一个对象来使用它的监视器,它更强大,语义更清晰(这就是我喜欢的)他们)。
**** 编辑 ****
另外,还有一个小建议。 Thread.currentThread().setName("X")
实际上可以通过 this.setName("X")
进行更改,因为您的对象是线程并且知道自己(但你不能在主线程上这样做)。不过,我建议完全删除它,因为 Thread 类公开了一个构造函数,允许您预先设置该名称,因此您可以:
class X extends Thread {
public X() {
super("X")
}
public void run(){
try {
...
}
}
class OtherThread extends Thread{
Thread t;
public OtherThread(Thread x){ // pass the X thread to this thread
super("OtherThread");
this.t = x;
}
public void run(){
try {
...
}
}
关于java - 如何使线程 - notify()/notifyAll() 私有(private),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29654549/