源无极

导航

 

一、方法wait()锁释放,notify()锁不释放

(一)wait()锁释放的案例

 

package com.it.po.thread8;

public class Service1 {

    public void methodA(Object lock){
        synchronized (lock){
            try {
                System.out.println("线程 "+Thread.currentThread().getName()+" begin wait");
                lock.wait();
                System.out.println("线程 "+Thread.currentThread().getName()+" end wait");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }



    }

}

 

package com.it.po.thread8;
public class MyThread4_1 extends Thread {
private Object lock;
    public MyThread4_1(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service1().methodA(lock);
    }
}

 

package com.it.po.thread8;
public class MyThread4_2 extends Thread {
private Object lock;
    public MyThread4_2(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service1().methodA(lock);
    }
}
package com.it.po.thread8;
import java.security.acl.LastOwnerException;
public class Run5 {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        MyThread4_1 my1 = new MyThread4_1(lock);
        MyThread4_2 my2 = new MyThread4_2(lock);
        my1.setName("A");
        my2.setName("B");
        my1.start();
        my2.start();
    }
}

 

线程 B begin wait
线程 A begin wait

 

 释放线程才会出现打印两个线程

 将lock.wait() 改成Thread.sleep()就是同步的 效果。

 

(二)、线程notify不释放锁

 

package com.it.po.thread8;
import java.sql.Time;
public class Service2 {
    public void methodA(Object lock){
        synchronized (lock){
            try {
                System.out.println("线程 "+Thread.currentThread().getName()+" begin wait");
                lock.wait();
                System.out.println("线程 "+Thread.currentThread().getName()+" end wait");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void methodB(Object lock){
        synchronized (lock){
            try {
                System.out.println("线程 "+Thread.currentThread().getName()+" begin notify");
                System.out.println("begin time= "+System.currentTimeMillis());
                lock.notify();
                Thread.sleep(4000);
                System.out.println("end time= "+System.currentTimeMillis());
                System.out.println("线程 "+Thread.currentThread().getName()+" end notify");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
package com.it.po.thread8;
public class MyThread5_1 extends Thread {
private Object lock;
    public MyThread5_1(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service2().methodA(lock);
    }
}
package com.it.po.thread8;
public class MyThread5_2 extends Thread {
private Object lock;
    public MyThread5_2(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service2().methodB(lock);
    }
}
package com.it.po.thread8;
public class Run6 {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        MyThread5_1 my1 = new MyThread5_1(lock);
        MyThread5_2 my2 = new MyThread5_2(lock);
        my1.setName("A");
        my2.setName("B");
        my1.start();
        Thread.sleep(100);
        my2.start();
    }
}

 

线程 A begin wait
线程 B begin notify
begin time= 1574518908105
end time= 1574518912105
线程 B end notify
线程 A end wait

 (三)当wait遇到interrupt方法

 

 

package com.it.po.thread8;
public class Service1 {
    public void methodA(Object lock){
        synchronized (lock){
            try {
                System.out.println("线程 "+Thread.currentThread().getName()+" begin wait");
                lock.wait();
                System.out.println("线程 "+Thread.currentThread().getName()+" end wait");
            } catch (InterruptedException e) {
                System.out.println("wait 遇到interrupt。。。");
                e.printStackTrace();
            }
        }



    }

}

 

 

package com.it.po.thread8;

public class MyThread6_1 extends Thread {
private Object lock;
    public MyThread6_1(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service1().methodA(lock);
    }
}
package com.it.po.thread8;
public class Run7 {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        MyThread6_1 my1 = new MyThread6_1(lock);
        my1.setName("A");
        my1.start();
        Thread.sleep(2000);
        my1.interrupt();
    }
}

 

 

线程 A begin wait
wait 遇到interrupt。。。
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.it.po.thread8.Service1.methodA(Service1.java:9)
    at com.it.po.thread8.MyThread6_1.run(MyThread6_1.java:11)

 

 

 总结:

1.执行同步代码块会释放锁

2.执行wait会释放锁。

3.执行notify不会释放锁

4.执行同步代码块时遇到异常会释放锁。

 (四)、只通知一个线程

执行notify时,只是随机通知一个线程进行唤醒。

package com.it.po.thread9;
public class Service1 {
public void methodA(Object lock){
        try {
            synchronized (lock) {
                System.out.println("线程 " + Thread.currentThread().getName() + " begin wait");
                lock.wait();
                System.out.println("线程 " + Thread.currentThread().getName() + " end wait");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

}
}

 

 

package com.it.po.thread9;
public class MyThread1_1 extends Thread {
private Object lock;
    public MyThread1_1(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service1().methodA(lock);
    }
}
package com.it.po.thread9;
public class MyThread1_2 extends Thread {
private Object lock;
    public MyThread1_2(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service1().methodA(lock);
    }
}
package com.it.po.thread9;
public class MyThread1_3 extends Thread {
private Object lock;
    public MyThread1_3(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
        new Service1().methodA(lock);
    }
}
package com.it.po.thread9;
public class NotifyThread1_4 extends Thread {
private Object lock;
    public NotifyThread1_4(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
       synchronized (lock){
           lock.notify();
       }
    }
}

 

 

package com.it.po.thread9;

public class Run1 {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        MyThread1_1 my1 = new MyThread1_1(lock);
        MyThread1_2 my2 = new MyThread1_2(lock);
        MyThread1_3 my3 = new MyThread1_3(lock);
        NotifyThread1_4 my4 = new NotifyThread1_4(lock);
        my1.setName("A");
        my2.setName("B");
        my3.setName("C");
        my1.start();
        my2.start();
        my3.start();
        Thread.sleep(2000); //保证先执行wait
        my4.setName("D");
        my4.start();

    }

}

 

 第一次执行

线程 B  begin wait
线程 C  begin wait
线程 A  begin wait
线程 B end wait

 

第二次执行

线程 A  begin wait
线程 C  begin wait
线程 B  begin wait
线程 A end wait

 

第三次执行

线程 C  begin wait
线程 B  begin wait
线程 A  begin wait
线程 C end wait

 

 

 修改成唤醒全部线程

package com.it.po.thread9;
public class NotifyThread1_4 extends Thread {
private Object lock;
    public NotifyThread1_4(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
       synchronized (lock){
           lock.notify();
           lock.notify();
           lock.notify();
       }
    }
}

 

 

线程 A  begin wait
线程 C  begin wait
线程 B  begin wait
线程 A end wait
线程 B end wait
线程 C end wait

 

 (五)、唤醒所有线程(上面的例子修改)

可以用notifyAll

package com.it.po.thread9;
public class NotifyThread1_4 extends Thread {
private Object lock;
    public NotifyThread1_4(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        super.run();
       synchronized (lock){
           lock.notifyAll();

       }
    }
}

 

 

线程 A  begin wait
线程 B  begin wait
线程 C  begin wait
线程 C end wait
线程 B end wait
线程 A end wait

 

 

 (六)、方法wait(long)的使用

等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

package com.it.po.thread9;
import org.omg.CORBA.OBJ_ADAPTER;
public class Run2 {
    static  private Object lock=new Object();
    static private Runnable runnable =new Runnable() {
        @Override
        public void run() {
            try {
            synchronized (lock) {
                System.out.println("线程 wait begin " + System.currentTimeMillis());
                lock.wait(5000);
                System.out.println("线程 wait end   " + System.currentTimeMillis());
            }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    };
    public static void main(String[] args) throws InterruptedException {
        runnable.run();
    }

}

 

线程 wait begin 1574592435421
线程 wait end   1574592440422

 

 

在wait中获得通知

package com.it.po.thread9;

import com.it.po.thread05.Task1;
import org.omg.CORBA.OBJ_ADAPTER;

public class Run2 {
    static  private Object lock=new Object();
    static private Runnable runnable =new Runnable() {
        @Override
        public void run() {
            try {
            synchronized (lock) {
                System.out.println("线程 wait begin " + System.currentTimeMillis());
                lock.wait(5000);
                System.out.println("线程 wait end   " + System.currentTimeMillis());
            }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    };

    static private Runnable runnable2 =new Runnable() {
        @Override
        public void run() {
                synchronized (lock) {
                    System.out.println("线程 notify begin " + System.currentTimeMillis());
                    lock.notify();
                    System.out.println("线程 notify end   " + System.currentTimeMillis());
                }
        }
    };
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(runnable);
        t1.start();
        Thread.sleep(2000);
        Thread t2 = new Thread(runnable2);
        t2.start();
    
    }

}

 

线程 wait begin 1574593179679
线程 notify begin 1574593181679
线程 notify end   1574593181679
线程 wait end   1574593181679

 

 

2s后被唤醒。

注意:如修改如下

package com.it.po.thread9;
import com.it.po.thread05.Task1;
import org.omg.CORBA.OBJ_ADAPTER;
public class Run2 {
    static  private Object lock=new Object();
    static private Runnable runnable =new Runnable() {
        @Override
        public void run() {
            try {
            synchronized (lock) {
                System.out.println("线程 wait begin " + System.currentTimeMillis());
                lock.wait(5000);
                System.out.println("线程 wait end   " + System.currentTimeMillis());
            }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    };

    static private Runnable runnable2 =new Runnable() {
        @Override
        public void run() {
                synchronized (lock) {
                    System.out.println("线程 notify begin " + System.currentTimeMillis());
                    lock.notify();
                    System.out.println("线程 notify end   " + System.currentTimeMillis());
                }
        }
    };
    public static void main(String[] args) throws InterruptedException {
      /*  Thread t1 = new Thread(runnable);
        t1.start();
        Thread.sleep(2000);
        Thread t2 = new Thread(runnable2);
        t2.start();*/

        runnable.run();
        Thread.sleep(2000);
        runnable2.run();
    }

}

 

这就一个线程mian执行

线程 wait begin 1574593273487
线程 wait end   1574593278488
线程 notify begin 1574593280488
线程 notify end   1574593280488

 

 (七)、通知过早

package com.it.po.thread9;

public class Run3 {
    static  private Object lock=new Object();
    static private Runnable runnable1 =new Runnable() {
        @Override
        public void run() {
            try {
            synchronized (lock) {
                System.out.println("线程1 wait begin " );
                lock.wait();
                System.out.println("线程1 wait end   " );
            }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    };

    static private Runnable runnable2 =new Runnable() {
        @Override
        public void run() {
                synchronized (lock) {
                    System.out.println("线程 2 begin " );
                    lock.notify();
                    System.out.println("线程 2 end   " );
                }
        }
    };
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(runnable1);
        t1.start();
       // Thread.sleep(2000);
        Thread t2 = new Thread(runnable2);
        t2.start();


    }

}

 

可能出现先通知在wait

 

 

线程 2 begin 
线程 2 end   
线程1 wait begin 

 修改

package com.it.po.thread9;
public class Run4 {
      private Object lock=new Object();
     private Boolean isFirstRun=false;
     private Runnable runnable1 =new Runnable() {
        @Override
        public void run() {
            try {
            synchronized (lock) {
                while (isFirstRun==false) {
                    System.out.println("线程1 wait begin ");
                    lock.wait();
                    System.out.println("线程1 wait end   ");
                }
            }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    };

     private Runnable runnable2 =new Runnable() {
        @Override
        public void run() {
                synchronized (lock) {
                    System.out.println("线程 2 begin " );
                    lock.notify();
                    System.out.println("线程 2 end   " );
                    isFirstRun=true;
                }
        }
    };
    public static void main(String[] args) throws InterruptedException {
        Run4 run4 = new Run4();
        Thread t1 = new Thread(run4.runnable1);
        t1.start();
       Thread.sleep(2000);
        Thread t2 = new Thread(run4.runnable2);
        t2.start();


    }

}

 

 

线程1 wait begin 
线程 2 begin 
线程 2 end   
线程1 wait end  

 

while()循环一次 

  (八)、等待wait的条件发送变化

 

package com.it.po.thread9;
public class Add {
private String lock;
    public Add(String lock) {
        this.lock = lock;
    }
    public void add(){
    synchronized (lock){
        ValueObject.list.add("po");
        lock.notifyAll();
    }
}

}

 

 

package com.it.po.thread9;
import java.util.ArrayList;
import java.util.List;
public class ValueObject {
public static List<String> list=new ArrayList();
}

 

 

package com.it.po.thread9;
public class Subtract {
private String lock;
    public Subtract(String lock) {
        this.lock = lock;
    }
    public void subtract(){
        try {
            synchronized (lock){
             if(ValueObject.list.size()==0){
                 System.out.println("线程 "+Thread.currentThread().getName()+" begin wait");
                  lock.wait();
                 System.out.println("线程 "+Thread.currentThread().getName()+" end wait");
             }
             ValueObject.list.remove(0);
             System.out.println("list size= "+ValueObject.list.size());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

 

package com.it.po.thread9;
public class ThreadAdd extends Thread {
private Add add;
    public ThreadAdd(Add add) {
        this.add = add;
    }
    @Override
    public void run() {
        super.run();
        add.add();
    }
}

 

package com.it.po.thread9;
public class SubtractThread extends Thread {
private Subtract subtract;
    public SubtractThread(Subtract subtract) {
        this.subtract = subtract;
    }
    @Override
    public void run() {
        super.run();
        subtract.subtract();
    }
}

 

package com.it.po.thread9;
import com.it.po.thread03.ThreadA;
public class Run5 {
    public static void main(String[] args) throws InterruptedException {
      String lock =  new String("po");
        Add add = new Add(lock);
        Subtract subtract = new Subtract(lock);
        SubtractThread s1 = new SubtractThread(subtract);
        s1.setName("A");
        SubtractThread s2 = new SubtractThread(subtract);
        s2.setName("B");
        //先删除两次
        s1.start();
        s2.start();
        Thread.sleep(1000);
        ThreadAdd a1 = new ThreadAdd(add);
        a1.start();
    }

}

 

在main中两条 sleep()之前,两个SubtractThread 进入wait状态,

1s过后,执行a1.start(),唤醒两条线程,第一天正确删除,第二个则报错

线程 A begin wait
线程 B begin wait
线程 B end wait
list size= 0
线程 A end wait
Exception in thread "A" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:653)
    at java.util.ArrayList.remove(ArrayList.java:492)
    at com.it.po.thread9.Subtract.subtract(Subtract.java:15)
    at com.it.po.thread9.SubtractThread.run(SubtractThread.java:10)

 

如果解决报错

package com.it.po.thread9;
public class Subtract {
private String lock;
    public Subtract(String lock) {
        this.lock = lock;
    }
    public void subtract(){
        try {
            synchronized (lock){
             while (ValueObject.list.size()==0){
                 System.out.println("线程 "+Thread.currentThread().getName()+" begin wait");
                  lock.wait();
                 System.out.println("线程 "+Thread.currentThread().getName()+" end wait");
             }
             ValueObject.list.remove(0);
             System.out.println("list size= "+ValueObject.list.size());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

 

 

线程 B begin wait
线程 A begin wait
线程 A end wait
list size= 0
线程 B end wait
线程 B begin wait

 

分析:

1.注意其实线程s1和s2是同步的,只不过调用wait释放锁,才有异步的感觉

2.当执行 a1.start(); 添加一个元素再通知s1 和s2线程时,其中一个

线程发现ValueObject.list.size()=1,这个线程结束while成功删除元素,

另一个线程执行完while之后发现 ValueObject.list.size()==0 又进入wait状态

 

 

 

 

 

 

 

posted on 2019-11-23 22:23  源无极  阅读(134)  评论(0)    收藏  举报