java - 如何使线程 - notify()/notifyAll() 私有(private)

标签 java multithreading

有办法阻止线程调用 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/

相关文章:

c++ - vmware中的线程编程, 'process scheduling'没有发生

java - 如何在 Netbeans 的 Jar 中嵌入 Javadoc

java - Couchbase Memcached 过滤器

python - 从线程目标访问 `self`

Android 我可以运行多少个线程?

android - recyclerview 中不正确的线程错误导致的 Realm 访问

c# - 在 .NET 中开发多线程应用程序和并行编程之间有什么区别?

android - 当不存在时 Eclipse 给出错误(Snow Leopard 和 Android)

java - Selenium WebDriver Firefox 在 Eclipse 中执行 Java 时出现错误异常?

java - 如何在android中将颜色资源设置为墙纸?