精华内容
下载资源
问答
  • 这三个方法依赖于同一个锁对象,,也就是说只能采用同一个锁的对象的notify唤醒该锁wait造成的挂起。注意在调用notify和wait方法的时候,首先得获取该锁的使用权限。 wait 方法将线程阻塞。如果有十个线程调用了...
       这三个方法依赖于同一个锁对象,,也就是说只能采用同一个锁的对象的notify唤醒该锁wait造成的挂起。注意在调用notify和wait方法的时候,首先得获取该锁的使用权限。

    wait     方法将线程阻塞。如果有十个线程调用了某个锁对象的wait方法,则10个线程都挂起。如果将这十个线程都唤醒,则需要调用10次该锁对象的notify方法,或者调用一次该锁对象notifyAll方法。

    notify   唤醒单个线程。

    notifyAll 唤醒所有的线程。


    例子如下:雇主有5个工人。当雇主干活命令的使用,则工人工作。如不发送干活命令则工人等待。

     说明:   雇主(employer)有个锁对象(command),雇主雇佣了5个工人(eployee)。
             工人的工作(run方法)使用了雇主的锁对象(command)来挂起。
             当雇主对所对象command唤醒(调用notify方法)则工人继续工作。
     


    public class Employee implements Runnable {

          String command;
          
          Employee(String command)
          {
                 this.command = command;
          }

           @Override
           public void run() {            
                 synchronized(command )
                {                
                     System. out.println("I am waiting by invoking command.wait() method");
                       try {
                           //工人在等待雇主的干活命令。调用雇主的锁对象,挂起当前线程。  
                             command.wait();
                            
                  System. out.println("Employer notify me by invoking command.notify() method, then I will do my work");
                            
                      } catch (InterruptedException e) {
                             // TODO Auto-generated catch block
                            e.printStackTrace();
                      }
                            
                      System. out.println("I am working" );   
                }           
          }
    }




    public class Employer {
          //雇主的锁对象,使用该command.notify方法来要工人干活
           String command = "command";
           public static void main(String[] sss) throws InterruptedException {
               
                Employee mployee1 = new Employee(command);
                Employee mployee2 = new Employee(command);
                Employee mployee3 = new Employee(command);
                Employee mployee4 = new Employee(command);
                Employee mployee5 = new Employee(command);

                Thread t1 = new Thread(mployee1);
                Thread t2 = new Thread(mployee2);
                Thread t3 = new Thread(mployee3);
                Thread t4 = new Thread(mployee4);
                Thread t5 = new Thread(mployee5);

                t1.start();
                t2.start();
                t3.start();
                t4.start();
                t5.start();

                Thread. sleep(1000);
                
                 //注意需要得到对应锁对象的使用权限
                 synchronized(command)
                {
                //此次调用了两次notify则会有两个工人工作, 如果调用notifyAll则所有的线程都唤醒,所有的工人都干活

                   command.notify();
                   command.notify();
                }

          }
    }
    展开全文
  • Java线程挂起唤醒

    千次阅读 2013-08-17 14:11:15
    private Thread mythread; public void start() {  if (mythread==null){ mythread=new Thread(); mythread.start(); } else {  mythread.resume(); } } public void run() ...try{

    private Thread mythread;

    public void start()

    if (mythread==null){

    mythread=new Thread();

    mythread.start();

    }

    else { 

    mythread.resume();

    }

    }
    public void run()

    {  

    while(true) {   

    try{

    sleep(100);

            catch(InterruptedException e) {}

    }

    }
    public void stop()

    {

    mythread.suspend();

    }

    展开全文
  • 1. 线程的挂起和唤醒  挂起实际上是让线程进入“非可执行”状态下,在这个状态下CPU不会分给...在线程挂起后,可以通过重新唤醒线程来使之恢复运行。 挂起的原因可能是如下几种情况:  (1)通过调用sleep()

    转自:http://blog.chinaunix.net/uid-122937-id-215913.html

    1. 线程的挂起和唤醒
          挂起实际上是让线程进入“非可执行”状态下,在这个状态下CPU不会分给线程时间片,进入这个状态可以用来暂停一个线程的运行;在线程挂起后,可以通过重新唤醒线程来使之恢复运行。

    挂起的原因可能是如下几种情况:
         (1)通过调用sleep()方法使线程进入休眠状态,线程在指定时间内不会运行。
         (2)通过调用join()方法使线程挂起,使自己等待另一个线程的结果,直到另一个线程执行完毕为止。
         (3)通过调用wait()方法使线程挂起,直到线程得到了notify()和notifyAll()消息,线程才会进入“可执行”状态。
         (4)使用suspend挂起线程后,可以通过resume方法唤醒线程。
          虽然suspend和resume可以很方便地使线程挂起和唤醒,但由于使用这两个方法可能会造成死锁,因此,这两个方法被标识为 deprecated(抗议)标记,这表明在以后的jdk版本中这两个方法可能被删除,所以尽量不要使用这两个方法来操作线程。

          调用sleep()、yield()、suspend()的时候并没有被释放锁
          调用wait()的时候释放当前对象的锁

          wait()方法表示,放弃当前对资源的占有权,一直等到有线程通知,才会运行后面的代码。
          notify()方法表示,当前的线程已经放弃对资源的占有,通知等待的线程来获得对资源的占有权,但是只有一个线程能够从wait状态中恢复,然后继续运行wait()后面的语句。
          notifyAll()方法表示,当前的线程已经放弃对资源的占有,通知所有的等待线程从wait()方法后的语句开始运行。 

    2.
    等待和锁实现资源竞争

          等待机制与锁机制是密切关联的,对于需要竞争的资源,首先用synchronized确保这段代码只能一个线程执行,可以再设置一个标志位condition判断该资源是否准备好,如果没有,则该线程释放锁,自己进入等待状态,直到接收到notify,程序从wait处继续向下执行。

    1. synchronized(obj) {
    2.   while(!condition) {
    3.    obj.wait();
    4.   }
    5.   obj.doSomething();
    6. }
    以上程序表示只有一个线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A释放该锁,进入wait()。

          在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
    1. synchronized(obj) {
    2.  condition = true;
    3.  obj.notify();
    4. }
    需要注意的是:
      # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。
      # 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码段内唤醒A。
      # 当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。
      # 如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)
      # obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。
      # 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。


    例1:
    单个线程对多个线程的唤醒

          假设只有一个Game对象,但有3个人要玩,由于只有一个游戏资源,必须必然依次玩。
    1. /**
    2.  * 玩游戏的人.
    3.  * @version V1.0 ,2011-4-8
    4.  * @author xiahui
    5.  */
    6. public class Player implements Runnable {
    7.     private final int id;
    8.     private Game game;

    9.     public Player(int id, Game game) {
    10.         this.id = id;
    11.         this.game = game;
    12.     }


    13.     public String toString() {
    14.         return "Athlete<" + id + ">";
    15.     }

    16.     public int hashCode() {
    17.         return new Integer(id).hashCode();
    18.     }
    19.     
    20.     public void playGame() throws InterruptedException{
    21.         System.out.println(this.toString() + " ready!");
    22.         game.play(this);
    23.     }

    24.     public void run() {
    25.         try {
    26.             playGame();
    27.         } catch (InterruptedException e) {
    28.             System.out.println(this + " quit the game");
    29.         }
    30.     }
    31. }
    游戏类,只实例化一个
    1. import java.util.HashSet;
    2. import java.util.Iterator;
    3. import java.util.Set;

    4. /**
    5.  * 游戏类.
    6.  * @version V1.0 ,2011-4-8
    7.  * @author xiahui
    8.  */
    9. public class Game implements Runnable {
    10.     private boolean start = false;

    11.     public void play(Player player) throws InterruptedException {
    12.         synchronized (this) {
    13.             while (!start)
    14.                 wait();
    15.             if (start)
    16.                 System.out.println(player + " have played!");
    17.         }
    18.     }

    19.     //通知所有玩家
    20.     public synchronized void beginStart() {
    21.         start = true;
    22.         notifyAll();
    23.     }

    24.     public void run() {
    25.         start = false;
    26.         System.out.println("Ready......");
    27.         System.out.println("Ready......");
    28.         System.out.println("game start");
    29.         beginStart();//通知所有玩家游戏准备好了
    30.     }

    31.     public static void main(String[] args) {
    32.         Set<Player> players = new HashSet<Player>();
    33.         //实例化一个游戏
    34.         Game game = new Game();
    35.         
    36.         //实例化3个玩家
    37.         for (int i = 0; i < 3; i++)
    38.             players.add(new Player(i, game));
    39.         
    40.         //启动3个玩家
    41.         Iterator<Player> iter = players.iterator();
    42.         while (iter.hasNext())
    43.             new Thread(iter.next()).start();
    44.         Thread.sleep(100);
    45.         
    46.         //游戏启动
    47.         new Thread(game).start();
    48.     }
    49. }
    程序先启动玩家,三个玩家竞争玩游戏,但只能有一个进入play,其他二个等待,进入的玩家发现游戏未准备好,所以wait,等游戏准备好后,依次玩。
    运行结果
    1. Athlete<0> ready!
    2. Athlete<1> ready!
    3. Athlete<2> ready!
    4. Ready......
    5. Ready......
    6. game start
    7. Athlete<2> have played!
    8. Athlete<1> have played!
    9. Athlete<0> have played!

    3.一次唤醒一个线程
          一次唤醒所有玩家,但只有一个玩家能玩,不如一个一个唤醒
    将上面的代码修改如下
    1.     public void play(Player player) throws InterruptedException {
    2.         synchronized (this) {
    3.             while (!start)
    4.                 wait();
    5.             if (start){
    6.                 System.out.println(player + " have played!");
    7.                 notify();//玩完后,通知下一个玩家来玩
    8.             }
    9.         }
    10.     }
    11.     //通知一个玩家
    12.     public synchronized void beginStart() {
    13.         start = true;
    14.         notify();
    15.     }

    4.suspend挂起
          该方法已不建议使用,例子如下
    例2:suspend方法进行挂起和唤醒
    1. /**
    2.  * suspend方法进行挂起和唤醒.
    3.  * @version V1.0 ,2011-3-27 
    4.  * @author xiahui
    5.  */
    6. public class SuspendThread implements Runnable{
    7.     public void run() {
    8.         try {
    9.             Thread.sleep(10);
    10.         } catch (Exception e) {
    11.             System.out.println(e);
    12.         }
    13.         for (int i = 0; i <= 1; i ) {
    14.             System.out.println(Thread.currentThread().getName() ":" i);
    15.         }
    16.     }

    17.     public static void main(String args[]) throws Exception {
    18.         Thread th1 = new Thread(new SuspendThread(),"thread1");
    19.         Thread th2 = new Thread(new SuspendThread(),"thread2");
    20.         System.out.println("Starting " th1.getName() "...");
    21.         th1.start();
    22.         System.out.println("Suspending " th1.getName() "...");
    23.         //Suspend the thread.
    24.         th1.suspend();
    25.         th2.start();
    26.         th2.join();
    27.         // Resume the thread.
    28.         th1.resume();
    29.     }
    30. }
    运行结果
    1. Starting thread1...
    2. Suspending thread1...
    3. thread2:0
    4. thread2:1
    5. thread1:0
    6. thread1:1
    注意:
          如果注释掉//th2.join();则thread2运行后,主线程会直接执行thread1的resume,运行结果可能会是
    1. Starting thread1...
    2. Suspending thread1...
    3. thread1:0
    4. thread1:1
    5. thread2:0
    6. thread2:1


    参考文献
    1.Java多线程设计模式:了解wait/notify机制. http://webservices.ctocio.com.cn/wsjavtec/335/8580335.shtml
    2.Java中使用wait()与notify()实现线程间协作. http://www.bianceng.cn/Programming/Java/201103/25215.htm

    展开全文
  • Java线程挂起

    2017-06-07 21:47:00
    Java提供了2个关于线程挂起和恢复的接口,一个是suspend用于挂起线程,一个是resume接口用于唤醒线程。这2个线程都是被废弃的接口,因为他们和stop一样是不安全的。 suspend挂起线程不会释放线程当前占用的资源,...

    ##简介

    Java提供了2个关于线程挂起和恢复的接口,一个是suspend用于挂起线程,一个是resume接口用于唤醒线程。这2个线程都是被废弃的接口,因为他们和stop一样是不安全的。 suspend挂起线程不会释放线程当前占用的资源,并且resume比suspend提前调用的话就会造成线程一直挂起,并且从堆栈中不容易分析,因为suspend挂起的线程是状态是Runnable,这就意味着常规的分析方法和工具很难定位到问题。只有对多次堆栈的dump进行全部分析才有机会定位到问题。 下面展示一个因为先执行了resume而导致挂死的例子。

    不优雅的suspend

    import java.util.concurrent.TimeUnit;
    
    public class SuspendTest {
        
        static Object lock = new Object();
        
        @SuppressWarnings("deprecation")
        public static void main(String[] args) {
            Suspend s1 = new Suspend();
            Suspend s2 = new Suspend();
            s1.start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            s1.resume();
            s2.start();
            s2.resume();
        }
        
        static class Suspend extends Thread{
            @SuppressWarnings("deprecation")
            @Override
            public void run() {
                synchronized(lock){
                    try {
                        TimeUnit.MILLISECONDS.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Thread.currentThread().suspend();
                }
            }
        }
    
    }
    

    上面的例子的一般情况s1是可以执行完成的,是因为先执行了suspend,后执行resume,而s2就被挂死了,因为s2先执行了resume,后执行的suspend。

    下面是挂死之后上的堆栈信息:

    "Thread-1" prio=6 tid=0x000000000c7bf000 nid=0x15a4 runnable [0x000000000d21e000]
       java.lang.Thread.State: RUNNABLE
        at java.lang.Thread.suspend0(Native Method)
        at java.lang.Thread.suspend(Unknown Source)
        at cn.d.concurrent.SuspendTest$Suspend.run(SuspendTest.java:34)
        - locked <0x00000007d5e99f78> (a java.lang.Object)
    

    从上面的堆栈信息分析可以知道被挂死的s2的线程状态是RUNNABLE,并且没有释放它锁占用的锁0x00000007d5e99f78。

    上面被挂死的原因有一部分是刻意为之,但是在多线程调度不确定的情况下不刻意,使用suspend也很容易找出挂死,因为它的确有一些问题,所以才会被废弃。

    suspend的代替方法

    需要用到suspend的地方基本都刻意替换为wait,notify模式,如果你想要简单实现,刻意考虑JUC提供的工具LockSupport。下面的例子使用LockSupport工具替换上面例子的suspend和resume方法。

    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.LockSupport;
    
    public class SuspendTest2 {
        
        static Object lock = new Object();
        
        public static void main(String[] args) {
            Suspend s1 = new Suspend();
            Suspend s2 = new Suspend();
            s1.start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            LockSupport.unpark(s1);
            s2.start();
            LockSupport.unpark(s2);
            
        }
        
        static class Suspend extends Thread{
            @Override
            public void run() {
                synchronized(lock){
                    try {
                        TimeUnit.MILLISECONDS.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    LockSupport.park();
                }
            }
        }
    
    }
    

    使用LockSupport工具的静态方法轻松加愉快的就解决了suspend和resume带来的问题。

    总结

    1. 尽量不要使用suspend来挂起线程
    2. 考虑使用wait,notify模式来代替suspend
    3. 考虑使用JUC的LockSupport来代替suspend

    转载于:https://my.oschina.net/u/2474629/blog/916690

    展开全文
  • 多线程之Java线程阻塞与唤醒

    万次阅读 2014-12-06 18:58:01
    线程的阻塞和唤醒在多...在Java发展史上曾经使用suspend()、resume()方法对于线程进行阻塞唤醒,但随之出现很多问题,比较典型的还是死锁问题。如下代码,主要的逻辑代码是主线程启动线程mt一段时间后尝试使用suspend
  • Java线程阻塞与唤醒

    2018-05-07 00:35:38
    Thread.suspend和Thread.resume因为容易导致死锁,很早以前就被标记为@deprecated,不建议使用了。我们把线程使用互斥锁访问的共享资源叫做...如果使用resume方法唤醒线程前需要获取监视器,那么死锁就会发生。当然...
  • LockSupport 可以挂起唤醒线程 park() 和 unpark() 是两个静态方法分别表示挂起唤醒 unpark() 可以执行在 park() 之前。标识这个线程已经做过唤醒操作,线程会直接略过阻塞。 package multhread; import java...
  • 这两天在研究多线程的使用方法,我们的需求是这样的:程序启动时,先让子线程处于运行状态,运行过程中会人为的更改该线程的运行状态为挂起,等待随机的时长之后,再把该线程重新唤醒,让其继续运行;人为挂起线程和...
  • 要想实现多个线程之间的协同,如:线程执行先后顺序、获取某个线程执行的结果等等。 涉及到线程之间相互通信,分为下面四类: 1 文件共享 2 网络共享 socket编程问题,非本文重点,不再赘述 3 共享变量 4 线程协作 - ...
  • java线程阻塞唤醒的四种方式 1. suspend与resume Java废弃 suspend() 去挂起线程的原因,是因为 suspend() 在导致线程暂停的同时,并不会去释放任何锁资源。其他线程都无法访问被它占用的锁。直到对应的线程执行 ...
  • 所谓线程挂起就是指暂停线程的执行(阻塞状态). 而恢复时就是让暂停的线程得以继续执行.(返回就绪状态) 二, 为何需要挂起和恢复线程. 我们来看1个经典的例子(生产消费): 1个仓库最多容纳6个产品, 制造者现在需要...
  • JAVA线程之三:线程的挂起和恢复

    千次阅读 2011-09-19 18:58:32
    1,概述:线程的挂起操作实质上就是使线程进入“非可执行”状态下...在线程挂起后,可以通过重新唤醒线程来使之恢复运行。当一个线程进入“非可执行”状态,即挂起状态时,必然存在某种原因使其不能继续运行,这些原因
  • Java线程等待唤醒机制(加深理解)

    万次阅读 多人点赞 2019-08-04 16:28:06
    今天看源码的时候遇到这样一个场景,某...下面代码是一个简单的线程唤醒机制示例,主要就是在Activity启动的时候初始化并start线程线程start后会进入等待状态,在onResume方法中执行notify方法唤醒线程。通过这样...
  • Java并发包源码学习系列:AbstractQueuedSynchronizer Java并发包源码学习系列:CLH同步队列及同步资源获取与释放 Java并发包源码学习系列:AQS共享式与独占式获取与释放资源的区别 Java并发包源码学习系列:...
  • 如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。以下是详细的唤醒方法:1. sleep() 方法:sleep(毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞...
  • 所谓线程挂起就是指暂停线程的执行(阻塞状态). 而恢复时就是让暂停的线程得以继续执行.(返回就绪状态) 二, 为何需要挂起和恢复线程. 我们来看1个经典的例子(生产消费): 1个仓库最多容纳6个产品, 制造者现在需要...
  • 如题 java有没有线程容器 提供了唤醒容器中所有挂起线程的方法 并且提供了挂起指定线程的方法 最好是java原生的 线程池等
  • 线程挂起和恢复的几种方法

    万次阅读 2015-10-27 21:47:59
    线程挂起和恢复方法(1):sleep()方法此种方法比较简单,哪个线程需要挂起就在哪个线程中直接调用:Thread.sleep(挂起的毫秒数);线程挂起和恢复方式(2):join()方法在实现多线程的两种方法这篇博文中值说明了...
  • java线程——阻塞与唤醒

    千次阅读 2016-06-03 19:23:26
    三、java线程的阻塞及唤醒 1. sleep() 方法: sleep(…毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞状态,期间得不到cpu的时间片,等到时间过去了,线程重新进入可执行状态。(暂停线程,不会...
  • 如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。以下是详细的唤醒方法:1. sleep() 方法sleep(毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞...
  • 一、线程挂起与恢复 1、在久的JDK版本中,提供了下面两个方法,但目前已经废弃了,Thread源码中都加了@Deprecated注解 thread.suspend() 该方法不会释放线程所占用的资源。如果使用该方法将某个线程挂起,则可能会...
  • java线程的等待与唤醒

    千次阅读 2014-08-29 16:24:11
    线程挂起后,可以通过重新唤醒线程来使之恢复运行。 挂起的原因可能是如下几种情况:  (1)通过调用sleep()方法使线程进入休眠状态,线程在指定时间内不会运行。  (2)通过调用join()方法使线程挂起,使...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,160
精华内容 12,864
关键字:

java线程挂起唤醒

java 订阅