zoukankan      html  css  js  c++  java
  • 多线程

    1)    通过yield ()函数,可使线程进入可执行状态,排程器从可执行状态的线程中重新进行排程。所以调用了yield()的函数也有可能马上被执行。
    2)    当调用yield ()函数后,线程不会释放它的“锁标志”。

    class TestThreadMethod extends Thread{
            public static int shareVar = 0;
            public TestThreadMethod(String name){
                super(name);
            }
            public synchronized void run(){
                for(int i=0; i<4; i++){
                    System.out.print(Thread.currentThread().getName());
                    System.out.println(" : " + i);
                    Thread.yield();
                }
            }
        }
        public class TestThread{
            public static void main(String[] args){
                TestThreadMethod t1 = new TestThreadMethod("t1");
                TestThreadMethod t2 = new TestThreadMethod("t2");
                t1.start();
                t1.start(); //(1)
                //t2.start(); (2)
            }
    

        
    运行结果为:
    t1 : 0
    t1 : 1
    t1 : 2
    t1 : 3
    t1 : 0
    t1 : 1
    t1 : 2
    t1 : 3
    从结果可知调用yield()时并不会释放对象的“锁标志”。
                    如果把代码(1)注释掉,并去掉代码(2)的注释,结果为:
    t1 : 0
    t1 : 1
    t2 : 0
    t1 : 2
    t2 : 1
    t1 : 3
    t2 : 2
    t2 : 3
    从结果可知,虽然t1线程调用了yield(),但它马上又被执行了。

     wait与notify是java同步机制中重要的组成部分。结合与synchronized关键字使用,可以建立很多优秀的同步模型。
      synchronized(this){ }等价于publicsynchronized void method(){.....}
       同步分为类级别和对象级别,分别对应着类锁和对象锁。类锁是每个类只有一个,如果static的方法被synchronized关键字修饰,则在这个方法被执行前必须获得类锁;对象锁类同。
       首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:
      java.lang.IllegalMonitorStateException:current thread not owner
      在调用wait的时候,线程自动释放其占有的对象锁,同时不会去申请对象锁。当线程被唤醒的时候,它才再次获得了去获得对象锁的权利。
      所以,notify与notifyAll没有太多的区别,只是notify仅唤醒一个线程并允许它去获得锁,notifyAll是唤醒所有等待这个对象的线程并允许它们去获得对象锁,只要是在synchronied块中的代码,没有对象锁是寸步难行的。其实唤醒一个线程就是重新允许这个线程去获得对象锁并向下运行。

       notifyAll,虽然是对每个wait的对象都调用一次notify,但是这个还是有顺序的,每个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是一个线程,在具体应用的时候,需要注意一下。

      wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能。因为都个对像都有锁,锁是每个对像的基础,当然操作锁的方法也是最基础了。

    wait():

    等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。

    调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。

    notify():

    唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

    调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

    notifyAll():

    唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

    通常,多线程之间需要协调工作:如果条件不满足,则等待;当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify。等待机制与锁机制是密切关联的。

    例如:
      

    synchronized(obj) {
      while(!condition) {
      obj.wait();
      }
      obj.doSomething();
      }
      


      当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
      在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A :
      
      

    synchronized(obj) {
      condition = true;
      obj.notify();
      }
      

    synchronized和wait()、notify()等的关系:

    1.有synchronized的地方不一定有wait,notify

    2.有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。

    另外,注意一点:如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是currentthread了。

  • 相关阅读:
    第三方驱动备份与还原
    Greenplum 解决 gpstop -u 指令报错
    yum安装(卸载)本地rpm包的方法(卸载本地安装的greenplum 5.19.rpm)
    Java JUC(java.util.concurrent工具包)
    netty 详解(八)基于 Netty 模拟实现 RPC
    netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包
    netty 详解(六)netty 自定义编码解码器
    netty 详解(五)netty 使用 protobuf 序列化
    netty 详解(四)netty 开发 WebSocket 长连接程序
    netty 详解(三)netty 心跳检测机制案例
  • 原文地址:https://www.cnblogs.com/Smile-123/p/5770270.html
Copyright © 2011-2022 走看看