wait,notify,synchronized一些闲谈

作为一名大三实习生,写了三个月后台,讲真,我自己都不敢说自己是学java得了,平时用来用去的都是springMVC框架的那些东西,那些东西自己又太菜无法每个地方都能参透,有时任务来的紧你只能“就是这样的”就蒙着头做了。不过,也确实学到很多东西,业务能力也稍稍提升了些,不像刚开始那样了·····
不能放弃对知识的渴求,这是我刚开始入职前对自己最基本的要求,现在慢慢找回吧。入正题:
说起wait,其实很容易让人联想起来其他两样东西:sleep,yield,这两样都是java给出的让本线程暂停的方法,sleep,作为Thread的静态方法(总不肯能把所有县城都锁了吧,也没意义),只是让本线程暂歇,不释放context(内容上下文)所拥有的锁,当然,使用它你并不需要事先拥有某样锁。yeild也是暂停本线程,让其他同优先级线程的线程先运行,如果没有同优先级的线程,则不起作用(继续运行)。wait则事先需要拥有某个对象的锁,这个对象可以很大,也可以小到byte,事实上后者在同步时更节省性能,拥有这个锁后,你可以使用你拥有的锁的这个对象的wait方法来使本线程暂停,等待其他线程唤醒,,,怎么唤醒,用notify啊,必须是这个对象的notify,而且你必须事先拥有这个对象的锁。好像条件挺苛刻,我怎么模拟来证实呢?`

public class Syn {
public static void main(String[] args) {
Thread h=new Thread(new My());
System.out.println(“子线程start”);
h.start();
synchronized (h) {
System.out.println(“lock start”);
try {
h.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“lock end”);
}
}
}

public class My implements Runnable {

@Override
public void run() {
    synchronized (this) {
        for(int i=0;i<10;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
        this.notify();
    }

}

}
`

你可以很清楚的看到,确实因为被锁,h实例中的打印才能“顺利”进行下去。可以看到,上面我们获取锁的方式是用synchronized,我在这实验的也只是利用了synchronized很小的语法,只是在方法中做同步块,当然它还可以修饰方法,修饰方法当然就有静态和动态之分。
做静态方法的修饰符时当然是对这个类的所有对象起作用,但是你要注意,当你在主线程调用类的静态锁方法时,如果你同时调用类的实例的实例方法时,两者可以“同时运行”,并没有想实现想的那样,类锁了之后,类的所有对象的synchronized块都必须等着其将类锁释放才能运行。其实如果你仔细想一下,这是对的!因为这两次锁的不是一个对象!!前者锁的是类,后者所得是对象,内存地址可定不一样,所得肯定不一样,我的实验代码:`public class WaitAndNotify {

public static void main(String[] args) {
    Thread h=new Thread(new Thread1());
    Thread m=new Thread(new Thread2());
    h.start();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    m.start();

}

}

public class Thread1 implements Runnable {

@Override
public synchronized void run() {
    //StaticClass l=new StaticClass();
        StaticClass .getNum();
        this.notify();

}

}
public class Thread2 implements Runnable {

@Override
public void run() {
    StaticClass cla=new StaticClass();
    cla.printChar();

}

}
`看结果就明白了,
那我们前面说的对类锁了之后,它的所有对象都锁了,是什么意思?当然是在调用这个类的静态synchronized方法时,这个类的其他静态synchronized方法被锁了(这个我做了实验证明了),当然synchronized锁的对象还可以是类如synchronized(My.class)这个基本和静态方法的差不多。当然终止当前线程的方法还有join方法,名字就可以看出来它是将另一个线程假如当前任务中,并且等待刚才加入的线程运行完之后才会继续运行刚才的线程,这个功能完全可以用wait和notify或者synchronized实现,感兴趣的自己试试。
java中只能暂停当前线程不能强制停止其他线程让本线程活干完吗?好像应该有这样的场景吧?是的有,但是那是以前的事,后来发现,这样会导致很多的bug就不建议用再到后来的废除了。。。不过java提供给我们一种更优雅的方法,使用interrupt,但是这种方法并不能百分百保证另一个线程被终止,必须由另一个线程自己去处理。那被interrupt的线程怎么知道别人interrput它了呢?有isInterrput()和interrputed()两种方法,但是区别是第二个在取得线程被interrput的状态后(true)又将其改为false,下次再判断时就会是false,而第一个不会改变状态。还有一条就是,当被interrput的线程中有类似sleep,wait,等动作后,就会抛出interrputtedException,所以这也提示你,你可以在catch中做一些return的事将线程终止。好了,就到这。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值