有一种方法可以阻止线程调用notify()
/ notifyAll()
?
然后,就可以在课堂内拨打notify
。
一种notify
方法私有。 (一种,我们知道,我们不能)
这里有一些代码,必须注意OtherThread
synchronized
中我想要阻止的内容:
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");
}
}
}
答案 0 :(得分:2)
嗯,答案是你做不到。我的意思是,您根本无法更改notify
/ wait
可见性(所有对象都设置为公开)
但是,我认为可见性不适合您。您正在使用X的实例作为您正在等待/通知的监视器。问题在于,您正在将X线程共享给其他线程,原因还有其他原因。因此,每个人都可以进行等待/通知。
我建议使用另一个对象作为监视器(而不是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
),而不是仅仅共享一个Object来使用它(这就是我喜欢它们的方式)。
****编辑****
另外,一个小建议。 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 {
...
}
}
类暴露了一个允许你事先设置该名称的构造函数,所以不用做你正在做的事情,你可以:
{{1}}
答案 1 :(得分:0)
您不能阻止任何代码调用notify
,因为它是Object
的公共方法,并且子类不能降低继承方法或字段的可见性。
答案 2 :(得分:0)
您可以简单地创建一个包含Thread
成员字段的包装类,但不能提供对notify()
&的访问权限。 notifyAll()
方法......
public class MyThreadWrapper {
private final Thread myThread;
public MyThreadWrapper(Runnable r) {
myThread = new Thread(r);
}
//notice we haven't expose notify/notifyAll...
}
现在你的主要用:创建线程:
MyThreadWrapper myLimitedThread = new MyThreadWrapper(someRunnable);
答案 3 :(得分:0)
等待并通知/ notifyAll属于Object类和公共方法,任何有权访问该对象的人都可以调用这些方法。
这里的关键点是访问对象,如果你只想让某个类有权访问某个对象并通知/ notifyAll,那么你需要将该对象封装到该类,不要将该对象返回到外部世界。
class X {
private Object lock;
public void someMethod() {
//lock.wait();
//lock.notify();
}
}
不确定您要做什么,但是如果您尝试跨不同线程同步对共享对象的访问,则有许多可用的结构取决于具体问题。