在多个实例上挂起,恢复和停止线程和多个线程的现代方法?

时间:2014-10-05 09:43:12

标签: java multithreading synchronized

在网上阅读了大量有关线程的内容后,在Herbert Schildt的书“完全参考Java”的帮助下,我知道

  

synchronized仅防止多个线程同时执行同一方法       实例。我说......在同一个例子中。

     

当一个线程正在为对象执行synchronized方法时,调用所有其他线程       同一个对象块的同步方法(暂停执行)直到第一个线程完成       与对象。注意......在同一个实例(对象)中。

     

第三,来自oracle docs,
      当一个synchronized方法退出时,它会自动建立一个发生在之前的RELATIONSHIP       任何后续调用同一对象的同步方法。这保证了       所有线程都可以看到对象状态的更改。这也涉及到工作       具有多个线程的相同对象。

但当情况出现在多个线程处理同一个类的不同实例时,我总体上感到困惑,无法弄清楚发生了什么以及它是如何发生的?

考虑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个实例。

主线程进入睡眠状态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会考虑这种变化。

暂停线程1 //这会打印。

主线程再次进入睡眠状态10秒钟。 在ob1上工作的线程没有产生任何输出。为什么? (因为前面提到的更改被考虑在内,这就是为什么在循环之后,wait()会暂停这个线程。我是否正确?)。

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

ob1调用synchronized方法:myresume(),在其中更改

suspendFlag为false和

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

在这里感到困惑:线程(在ob1上)如何能够自我复活(我的意思是如何改变旗帜,即使我不太清楚它是如何被暂停的。)

恢复线程一个//被打印。 因为o / p在那里,所以线程显然已经复活(恢复)。

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

在同一时间,另一个线程被暂停,同样的事情发生了。

还有一个问题:

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

1 个答案:

答案 0 :(得分:1)

  

ob1将其命名为mysuspend(),将suspendFlag更改为true。在这里感到困惑:线程会考虑这种变化   工作ob1。

     

主线程再次进入睡眠状态10秒钟。在ob1上工作的线程没有产生任何输出。为什么? (因为此前有变化   提到被考虑,这就是为什么去了之后   通过循环,wait()挂起这个线程。我纠正了吗?)。

是。由于可运行实例state的{​​{1}}已更改,并且仅影响在可运行实例'ob1'上运行的线程。

  

向另一个处理另一个对象的线程发出notify()//通知。

没有。 'ob1'唤醒正在对象的监视器上的单个线程。请注意关键字。由于java.lang.Object.notify()只有一个线程对其进行操作,因此将通知发布ob1的线程,而不是处理wait()的线程,它们是两个ob2正在处理{ {1}}属于同一类型。

  

线程(在ob1上)如何能够自我复活(我的意思是如何改变旗帜,即使我不太清楚它是如何得到的   暂停。)

绑定到different threads的线程可以监视two different runnable instances状态的变化。绑定到ob1的线程可以监视ob1状态的更改。

  

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

没有。只有处理该特定实例的线程才会受到影响。如果你想要那样,

ob2

这样,帖子ob2NewThread 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方法相互共享communicate实例和wait() {1}}。

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