`
atell
  • 浏览: 161637 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

wait时间到或被中断唤醒时,仍然需要等待获取锁。

阅读更多
import java.io.IOException;

public class Demo {

    /**
     * @param args
     * @throws IOException
     * @throws InterruptedException
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        
        T1 t1 = new T1();
        T2 t2 = new T2(t1);
        t1.start();
        t2.start();
        
    }


    static Integer i = 0;

    static class T1 extends Thread {

        public void run() {

            synchronized (i) {
                System.out.println("T1-在syn里");
                try {
                    i.wait(50L);//验证表明:wait时间到或被中断唤醒,不会继续执行或者跳到catch里
                                // (因为根本得不到执行,根本没法抛出InterruptedException,所以即使catch块放在syschronized外也一样 ),
                                //而是还需要等待获得锁。
                                //如果wait时间到或被中断唤醒,而T2还在syn里,那么T1还是会等待。
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束wait-T1");
                System.out.println("T1-在syn里");
                try {
                    Thread.sleep(10000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("T1-在syn里");
            }
            System.out.println("离开syn-T1");

        }
    }
    

    static class T2 extends Thread {

        Thread t1;
        public T2(Thread t1){
            this.t1 = t1;
        }
        
        public void run() {
            synchronized (i) {
                System.out.println("T2-在syn里");
                try {
                    t1.interrupt();
                    Thread.sleep(10000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("T2-还在syn里");
            }
            System.out.println("T2-离开syn");

        }
    }
}

 

验证表明: wait时间到或被中断唤醒,不一定会继续执行或者跳到catch里,而是还需要等待获得锁。
               如果wait时间到或被中断唤醒,而T2还在syn里,那么T1还是会等待。

 

另外,Thread.interrupt()唤醒线程之后,其实是设置了Thead的中断状态,后续任何时候,当该线程尝试wait,join,sleep时,中断状态都会起作用,使得Thread被中断,wait/join/sleep方法会抛出中断异常(wait需要获取锁后才能继续抛出异常)。这点javadoc有说明。

 

 

_____________________________________________________________________________

 

 

 

package com.atell;

import java.io.IOException;

public class Demo {

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {

        T1 t1 = new T1();
        T2 t2 = new T2(t1);
        t1.start();
        t2.start();

    }

    static Integer i = 0;

    static class T1 extends Thread {

        public void run() {

            synchronized (i) {
                System.out.println("T1-syn-start");
                try {
                    i.wait();// 可以被notify唤醒,也可以被interrupt唤醒,取决于T2中哪个操作先执行
                } catch (InterruptedException e) {
                    System.out.println("在wait时被中断");
                }
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    System.out.println("在sleep时被中断");
                }
                System.out.println("T1-syn-end");
            }
            System.out.println("离开syn-T1");

        }
    }

    static class T2 extends Thread {

        Thread t1;

        public T2(Thread t1){
            this.t1 = t1;
        }

        public void run() {
            synchronized (i) {
                System.out.println("T2-syn-start");
                //(1)如果先interrupt再notify,那么i.wait会因为interrupt而醒过来,notify则不对它起作用(如果此时Monitor的等待队列有其他线程,则notify必须去唤醒其他线程,不能虚发- Java语言规范17.8.4最后一句明确提到。)。
                //t1.interrupt();
                //i.notify();
                //(2)如果先notify再interrupt,那么i.wait会因为notify而醒过来,interrupt则对T1后续的sleep起作用。
                i.notify();
                t1.interrupt();
                System.out.println("T2-syn-end");
            }
            System.out.println("T2-离开syn");

        }
    }
}

 

验证表明: wait可以被notify唤醒,也可以被interrupt唤醒,取决于哪个操作先执行

(以上是看《Java语言规范17.8节》之后的结论)

 

分享到:
评论

相关推荐

    wait()编程wait()编程wait()编程wait()编程

    - `wait()`是可中断的,当线程被中断(`Thread.interrupt()`)时,`wait()`会抛出`InterruptedException`,这时线程需要处理中断状态,决定是否继续等待或结束。 - 使用`wait()`时,应避免无限期等待,通常建议...

    深入理解Wait、Notify和Wait与sleep区别

    时间到了或者被其他线程中断(调用`interrupt()`方法),线程会自动恢复执行,无需重新获取锁。 `wait()`, `notify()`和`notifyAll()`与`sleep()`的主要区别在于: - **权限和锁**:`wait()`, `notify()`和`...

    详解Java中的sleep()和wait()的区别

    总结一下,`sleep()` 主要是用来让线程短暂休眠,不涉及任何锁的问题,而 `wait()` 是线程间协作的关键,用于线程间的同步和通信,涉及到对象锁的释放和重新获取。理解并正确使用这两个方法是编写多线程程序的关键,...

    唤醒阻塞休眠线程示例

    5. **中断机制**:Java中的`Thread.interrupt()`方法可以设置线程的中断标志,处于阻塞状态(如等待I/O或持有锁)的线程在检测到中断时会抛出`InterruptedException`,从而有机会优雅退出。对于休眠的线程,`Thread....

    Java多线程同步(wait()notify()notifyAll())[文].pdf

    - notify()方法会唤醒一个正在等待该对象锁的线程,但不保证是哪个线程,且唤醒的线程需要获取到锁才能继续执行。 - notifyAll()则会唤醒所有等待该对象锁的线程,这些线程都将进入锁的竞争队列。 3. **...

    Waitqueue、Event及Semaphore的实现机制分析

    - **wait_event_timeout()**:类似于`wait_event()`,但增加了超时机制,如果在指定时间内事件未发生,线程会被唤醒。 - **wait_event_interruptible_timeout()**:允许线程被信号中断的版本,同时包含超时机制。 *...

    wait,notify等线程知识.pdf

    然而,这些线程仍然需要在获得锁后才能继续执行,这意味着只有一个线程能够在其他线程之前获取到锁并继续运行。 4. **Lock接口**: 为了解决`synchronized`关键字的一些限制,Java引入了Lock接口。Lock接口提供了...

    java sleep()和wait()

    - 当调用`wait()`方法时,线程会释放该对象的锁,而当线程被唤醒时(通过`notify()`或`notifyAll()`方法),它需要重新获取锁才能继续执行。 - 如果调用`wait()`方法的线程未获得该对象的锁,则会抛出`...

    线程的挂起、唤醒和终止

    现代编程实践中,我们通常使用`notify()`或`notifyAll()`方法来唤醒等待在对象监视器上的线程,这些方法与`synchronized`块或`wait()`方法一起使用。 线程的终止是指结束线程的执行。在Java中,最直接的方式是使用`...

    locks框架:接口.pdf

    3. **定时锁等待**:`tryLock(long time, TimeUnit unit)`方法允许设置等待获取锁的最长时间,超过这个时间仍未获取到锁,方法会返回。 Lock接口中最重要的实现类包括: 1. **ReentrantLock**:可重入锁,允许一个...

    java锁机制详解.pdf

    如果线程在执行过程中被中断或抛出异常,锁会在方法或代码块结束时自动释放。 2. **锁的特性**: - **互斥性**:同一时刻,只有一个线程能够持有锁,执行临界区代码。 - **可见性**:线程在释放锁后,其他线程...

    面试官:你是如何调用 wait()方法的?使用 if 块还是循环?为什么?

    当其他线程调用同一对象的`notify()`或`notifyAll()`方法时,等待的线程将被唤醒,进入就绪状态,但不会立即执行,而是需要再次竞争锁。 在调用`wait()`方法时,有两点非常重要: 1. **必须在同步块或同步方法中...

    JavaLock与Condition的理解Reentran

    1. await():使当前线程等待,直到被其他线程唤醒或被中断。线程被唤醒后,需要重新获取锁才能继续执行。 2. signal():唤醒一个在等待队列中等待的线程。 3. signalAll():唤醒所有等待队列中的线程。 五、...

    Java学习资料-详解Condition的await和signal等待/通知机制

    - `void signal()`: 唤醒等待在该`Condition`上的一个线程,将其从等待队列移动到同步队列,如果这个线程在同步队列中成功获取锁,那么它将从`await()`方法返回。 - `void signalAll()`: 唤醒所有等待在该`...

    Java中ReentrantLock的使用.docx

    尽管如此,ReentrantLock仍然有其独特之处,比如它可以提供公平锁和非公平锁的选择,支持中断锁等待,以及更细粒度的控制线程间的唤醒与等待。 1. **Lock接口**: - `lock()`:获取锁,如果无法立即获取,线程会被...

    Java中线程的等待与唤醒_动力节点Java学院整理

    当一个线程调用对象的wait()方法时,该线程会释放对象的锁,并进入等待状态,直到其他线程调用相同对象的notify()或notifyAll()方法来唤醒它。等待状态的线程不会占用CPU资源,而是被放入对象的等待队列中。一旦被...

    多线程同步和通讯完整示例

    - 支持公平锁和非公平锁,公平锁按照等待时间顺序获取锁,而非公平锁则不保证等待时间。 综上所述,多线程同步和通讯是并发编程的核心部分。synchronized关键字提供了基本的线程同步,而wait-notify机制和Lock接口...

    Java线程唤醒与阻塞常用方法共2页.pdf.zip

    - `wait()`: 这个方法属于`Object`类,当一个线程调用对象的`wait()`方法时,它会释放该对象的锁并进入等待状态,直到其他线程调用该对象的`notify()`或`notifyAll()`方法。线程在等待时会被放入对象的等待队列。 ...

    Java 多线程共享模型之管程(下).doc

    - **notifyAll()**: 类似于`notify()`,但它会唤醒等待队列中所有等待的线程,这些线程都将变为`BLOCKED`状态,然后竞争锁。 3. **示例代码解析** 在提供的代码示例中,我们创建了两个线程`t1`和`t2`,它们都尝试...

    Java锁的知识总结及实例代码共7页.pdf.zip

    - **ReentrantLock**:可重入锁,与synchronized具有相似的特性,但提供了更多的灵活性,如尝试获取锁、可中断的等待和公平锁等。 - **ReadWriteLock**:读写锁,允许多个读取线程同时访问,但写入操作是独占的,...

Global site tag (gtag.js) - Google Analytics