如何在Java项目中实现多线程的阻塞与唤醒

如何在Java项目中实现多线程的阻塞与唤醒?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

创新互联专注于维西网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供维西营销型网站建设,维西网站制作、维西网页设计、维西网站官网定制、小程序定制开发服务,打造维西网络公司原创品牌,更为您提供维西网站排名全网营销落地服务。

java线程的阻塞及唤醒

1. sleep() 方法:

sleep(…毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞状态,期间得不到cpu的时间片,等到时间过去了,线程重新进入可执行状态。(暂停线程,不会释放锁)

//测试sleep()方法
class Thread7 implements Runnable{
  @Override
  public void run() {
    for(int i=0;i<50;i++){
      System.out.println(Thread.currentThread().getName()+"num="+i);
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}
class Thread8 implements Runnable{
  @Override
  public void run() {
    for(int i=0;i<1000;i++){
      System.out.println(Thread.currentThread().getName()+"num="+i);
    }
  }
}
public static void main(String[] args) {
    /*
     * 测试线程阻塞
     */
    //测试sleep()方法
    Thread7 t7=new Thread7();
    Thread8 t8=new Thread8();
    Thread t81=new Thread(t8, "饺子");
    Thread t71=new Thread(t7, "包子");
    Thread t72=new Thread(t7, "面包");
    t71.start();
    t81.start();
    t72.start();
  }

2.suspend() 和 resume() 方法:。

挂起和唤醒线程,suspend()使线程进入阻塞状态,只有对应的resume()被调用的时候,线程才会进入可执行状态。(不建议用,容易发生死锁)

//测试suspend()和resume()方法
class Thread9 implements Runnable{
  @Override
  public void run() {
    for(long i=0;i<500000000;i++){
System.out.println(Thread.currentThread().getName()+" num= "+i);
    }
  }
}
public static void main(String[] args) {
  //测试suspend和resume
    Thread9 t9=new Thread9();
    Thread t91=new Thread(t9,"包子");
    t91.start();
    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    t91.suspend();
    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    t91.resume();
}

(在控制台打印输出的时候,会停顿2秒钟,然后再继续打印。)

3. yield() 方法:

会使的线程放弃当前分得的cpu时间片,但此时线程任然处于可执行状态,随时可以再次分得cpu时间片。yield()方法只能使同优先级的线程有执行的机会。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。(暂停当前正在执行的线程,并执行其他线程,且让出的时间不可知)

//测试yield()方法
class Thread10 implements Runnable{
  @Override
  public void run() {
    for(int i=0;i<100;i++){
      System.out.println(Thread.currentThread().getName()+" num= "+i);
      if(i==33){
        Thread.yield();
      }
    }
  }
}

public static void main(String[] args) {
  //测试yield
    Thread10 t10 =new Thread10();
    Thread t101=new Thread(t10, "包子");
    Thread t102=new Thread(t10, "面包");
    t101.start();
    t102.start();
}
/*
运行结果为:
……
包子 num= 24
包子 num= 25
包子 num= 26
包子 num= 27
包子 num= 28
包子 num= 29
包子 num= 30
包子 num= 31
包子 num= 32
包子 num= 33
面包 num= 0
面包 num= 1
面包 num= 2
面包 num= 3
……
面包 num= 30
面包 num= 31
面包 num= 32
面包 num= 33
包子 num= 34
包子 num= 35
包子 num= 36
包子 num= 37
包子 num= 38
……
*/

(可以看到,当数字为33时,都发生了交替。)

4.wait() 和 notify() 方法:

两个方法搭配使用,wait()使线程进入阻塞状态,调用notify()时,线程进入可执行状态。wait()内可加或不加参数,加参数时是以毫秒为单位,当到了指定时间或调用notify()方法时,进入可执行状态。(属于Object类,而不属于Thread类,wait( )会先释放锁住的对象,然后再执行等待的动作。由于wait( )所等待的对象必须先锁住,因此,它只能用在同步化程序段或者同步化方法内,否则,会抛出异常IllegalMonitorStateException.)

//测试wait()和notify()方法
//用生产者和消费者模式模拟这一过程
/*消费者 */
class Consumer implements Runnable {
private Vector obj;
  public Consumer(Vector v) {
    this.obj = v;
  }
  public void run() {
    synchronized (obj) {
      while (true) {
        try {
          if (obj.size() == 0) {
            obj.wait();
          }
          System.out.println("消费者:我要买面包。");
          System.out.println("面包数: " + obj.size());
          obj.clear();
          obj.notify();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }
}
/* 生产者 */
class Producter implements Runnable {
  private Vector obj;
  public Producter(Vector v) {
    this.obj = v;
  }
  public void run() {
    synchronized (obj) {
      while (true) {
        try {
          if (obj.size() != 0) {
            obj.wait();
          }
          obj.add(new String("面包"));
          obj.notify();
          System.out.println("生产者:面包做好了。");
          Thread.sleep(500);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  }
}
public static void main(String[] args) {
  //测试wait()和notify()
    Vector obj = new Vector();
    Thread consumer = new Thread(new Consumer(obj));
    Thread producter = new Thread(new Producter(obj));
    consumer.start();
    producter.start();
}

5.join()方法

也叫线程加入。是当前线程A调用另一个线程B的join()方法,当前线程转A入阻塞状态,直到线程B运行结束,线程A才由阻塞状态转为可执行状态。

//测试join
class Thread11 implements Runnable{
  @Override
  public void run() {
    System.out.println("Start Progress.");
    try {
      for(int i=0;i<5;i++){
        System.out.println("Thread11线程 : "+i);
        Thread.sleep(1000);
      }
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    System.out.println("End Progress.");
  }
}
public static void main(String[] args) {
  //测试join
    Thread11 t11=new Thread11();
    Thread t111=new Thread(t11);
    t111.start();
    try {
      t111.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    System.out.println("hi,I'm Main线程");
}
/*
运行结果为:
Start Progress.
Thread11线程 : 0
Thread11线程 : 1
Thread11线程 : 2
Thread11线程 : 3
Thread11线程 : 4
End Progress.
hi,I'm Main线程
*/

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注创新互联行业资讯频道,感谢您对创新互联的支持。


本文名称:如何在Java项目中实现多线程的阻塞与唤醒
网页链接:http://ybzwz.com/article/jdcpoe.html