java - 在多个实例上暂停、恢复和停止线程和多线程的现代方法?

标签 java multithreading synchronized

在网上阅读了大量有关线程的资料并在 Herbert Schildt 的书 The Complete Reference Java 的帮助下,我知道了

synchronized only prevents multiple threads from simultaneously executing the method in the same
instance. I said... in the same instance.

When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object. Notice ... in the same instance(object).

Thirdly, from oracle docs,
when a synchronized method exits, it automatically establishes a happens-before RELATIONSHIP with any subsequent invocation of a synchronized method for the same object. This guarantees that
changes to the state of the object are visible to all threads. This also involves working on the same object with multiple threads.

但是当涉及到多个线程处理同一个类的不同实例时,我变得很困惑,无法弄清楚发生了什么以及它是如何发生的?

考虑 Herbert Schildt 书中给出的示例:以现代方式暂停和恢复线程。

class NewThread implements Runnable {

String name; // name of thread
Thread t;
boolean suspendFlag;

NewThread(String threadname) {
    name = threadname;
    t = new Thread(this, name);
    System.out.println("New thread: " + t);
    suspendFlag = false;
    t.start(); // Start the thread
}

// This is the entry point for thread.
public void run() {
    try {
        for (int i = 15; i > 0; i--) {
            System.out.println(name + ": " + i);
            Thread.sleep(2000);
            synchronized (this) {
                while (suspendFlag) {
                    wait();
                }
            }
        }
    } catch (InterruptedException e) {
        System.out.println(name + " interrupted.");
    }
    System.out.println(name + " exiting.");
}

void mysuspend() {
    suspendFlag = true;
}

synchronized void myresume() {
    suspendFlag = false;
    notify();
}
}

主线程:

class SuspendResume {

public static void main(String args[]) {

    NewThread ob1 = new NewThread("One");
    NewThread ob2 = new NewThread("Two");

    try {
        Thread.sleep(10000);
        ob1.mysuspend();
        System.out.println("Suspending thread One");

        Thread.sleep(10000);
        ob1.myresume();
        System.out.println("Resuming thread One");

        ob2.mysuspend();
        System.out.println("Suspending thread Two");
        Thread.sleep(10000);

        ob2.myresume();
        System.out.println("Resuming thread Two");
    } catch (InterruptedException e) {
        System.out.println("Main thread Interrupted");
    }
    // wait for threads to finish
    try {
        System.out.println("Waiting for threads to finish.");
        ob1.t.join();
        ob2.t.join();
    } catch (InterruptedException e) {
        System.out.println("Main thread Interrupted");
    }

    System.out.println("Main thread exiting.");
}

}

输出如下:

New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
One: 15
Two: 15
One: 14
Two: 14
Two: 13
One: 13
Two: 12
One: 12
Two: 11
One: 11
Suspending thread One
Two: 10
Two: 9
Two: 8
Two: 7
Two: 6
Resuming thread One
Suspending thread Two
One: 10
One: 9
One: 8
One: 7
One: 6
Resuming thread Two
Waiting for threads to finish.
Two: 5
One: 5
Two: 4
One: 4
Two: 3
One: 3
Two: 2
One: 2
Two: 1
One: 1
Two exiting.
One exiting.
Main thread exiting.

我的理解: 有3个线程。除主线程外,还有 2 个正在处理同一类的 2 个实例。

主线程 hibernate 10 秒。 在此期间,另外两个人可以通过 for 循环进行 5 次。(因为他们也每人睡 2 秒。) 在此间隔期间标志为假,因此他们没有进入 while 循环。此间隔期间的 o/p 是:

One: 15
Two: 15
One: 14
Two: 14
Two: 13
One: 13
Two: 12
One: 12
Two: 11
One: 11

主线程唤醒。

ob1 调用它 mysuspend() 将 suspendFlag 更改为 true。 在这里困惑:线程工作ob1是否会考虑此更改。

挂起线程一//这得到打印。

主线程再次 hibernate 10 秒。 在 ob1 上工作的线程没有产生任何输出。为什么? (因为前面提到的更改已被考虑在内,这就是为什么在完成循环后,wait() 会暂停该线程。我说得对吗?)。

Two: 10
Two: 9
Two: 8
Two: 7
Two: 6

ob1 调用同步方法:myresume() 在其中发生变化

suspendFlag 为 false 和

向处理其他对象的其他线程发出通知()//通知。 我肯定知道一个通​​知命令从等待集中任意选择一个线程并将其标记为最终复活。并且锁还在。

这里很困惑:线程(在 ob1 上)如何能够自行复活(我的意思是,即使我不太清楚它是如何被挂起的,但如何通过更改标志来实现。)

Resuming thread One//被打印出来。 由于 o/p 在那里,线程显然已恢复(恢复),如下所示。

One: 10
One: 9
One: 8
One: 7
One: 6

同时,另一个线程被挂起,同样的事情发生了。

还有一个问题:

当一个线程正在为一个对象执行同步方法时,所有其他为另一个对象调用同步方法的线程都会阻塞(暂停执行),直到第一个线程完成该对象。我说别的对象?

最佳答案

ob1 calls it mysuspend() which changes the suspendFlag to true. Confused here: will this change be taken into consideration by thread working ob1.

Main thread goes to sleep again for 10 seconds. the thread working on ob1 didn't produce any output. WHY? (Because the change previously mentioned was taken into consideration and that's why after going through the loop, wait() suspends this thread. Am I correct?).

是的。由于可运行实例 'ob1'state 已更改,并且只会影响在可运行实例 'ob1' 上工作的线程。

issues a notify() // notification to the other thread working on the other object.

没有。 java.lang.Object.notify() 唤醒等待this 对象监视器的单个线程。请注意关键字this。由于 ob1 只有一个线程对其进行操作,发出 wait() 的线程将收到通知,而不是处理 ob2 的线程,它们是两个不同的线程,在同一类型的两个不同的可运行实例上工作。

How was the thread (on ob1) able to resurrect itself(I mean how come by just changing the flag even though i am not too clear how it got suspended.)

ob1绑定(bind)的线程可以监听ob1的状态变化。 ob2绑定(bind)的线程可以监听ob2的状态变化。

When one thread is executing a synchronized method for an object, does all other threads that invoke synchronized methods for the other object block (suspend execution) until the first thread is done with the object. I said the other object?

没有。只有在该特定实例上工作的线程才会受到影响。如果你想让它发生,

NewThread obj = new NewThread(); // single runnable instance
Thread ob1 = new Thread(obj); // two different threads sharing the same instance
Thread ob2 = new Thread(obj);

这样线程 ob1ob2 可以共享 obj 实例并使用 相互通信 obj 的 >wait()notify() 方法。

如果您正在寻找跨实例的同步线程,请查看:this .

关于java - 在多个实例上暂停、恢复和停止线程和多线程的现代方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26201449/

相关文章:

java - 从列中选择数据

java - 了解 Java 中的对象所有权

java - 同步Web服务方法有意义吗?

java - 如何在java中将字符串拆分为字符串和整数?

java - Java项目的自动分发

java - 如何编辑 JComboBox 并在 JEditorPane 中选择文本

c# - Queue<T>.Dequeue 返回 null

c# - C# 线程真的可以缓存一个值并忽略其他线程对该值的更改吗?

java - java中静态方法的线程安全

java - 同步与 ReadWriteLock 性能