上一篇文章讲到join()方法的时候,用到了一个函数即为yield()方法,它的作用是将cup让与具有相同优先级的线程去使用。本篇文章就为大家讲述线程中的一些关于等待和唤醒的函数。
sleep():
使当前线程暂停使用一段时间,让其它线程继续有机会执行,但是它并不释放对象锁,也就是说有synchronized关键字的时候,其它线程仍然不能访问其共享资源。sleep()方法需要用户去设置阻塞的时间。在用户设置sleep()方法的时候,该线程一定是不会被执行的,所以会让优先级低的线程有机会去执行。也就是说,如果优先级高的线程没有设置sleep()或者没有I/O阻塞的时候,优先级低的线程只能出于等待状态,只有当优先级较高的线程执行完毕后,它才有机会执行。
yield():
此方法与sleep()方法具有相同的功能,只是该方法的时间并不是由我们自己来设置的,而是由系统完成的,并且它只能让同优先级的线程有机会先执行。也就是说,执行yeld()方法,此线程会去寻找有没有与它优先级相同的线程,如果有,则让与它优先级相同的线程执行。若没有,则返回继续执行原来的线程。所以yield()方法只能给同优先级的线程执行的机会,而不会给低优先级的线程机会。(不给别人留活路啊)。
具体代码示例如下:
package sleepandwait; /** * 调用sleep()方法时,我们可以自己去指定该线程需要休息的时间, * 调用yield()方法时,我们并不知道该线程需要休息多长时间,而且 * yield()方法是让相同优先级的线程先执行。 * @author Administrator * */ public class Test { public static void main(String[] args) { Thread t1 = new Thread(new MyRunnable(2000)); t1.setPriority(9); t1.start(); Thread t2 = new Thread(new MyRunnable(3000)); t2.setPriority(6); t2.start(); Thread t3 = new Thread(new MyRunnable(5000)); t3.setPriority(9); t3.start(); } } class MyRunnable implements Runnable{ private int time; public MyRunnable(int time){ this.time = time; } @Override public void run() { try { Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } //Thread.yield(); //System.out.println("我是线程:" // +Thread.currentThread().getName()+ // "我调用的是yield()方法,我被阻塞了多久我不知道..."); System.out.println("我是线程:" +Thread.currentThread().getName()+"我被阻塞 了"+time+"秒!"); } }
当我们注释掉sleep()方法,换成wait()方法时,会看到是t1和t3先执行,最后是t2。
注意:sleep()和yield()都只是暂停当前线程的执行,并不会让出共享资源。
wait()、notify()、notifyAll():
wait()、notify()、notifyAll()都是用于协调多个线程对共享数据的存取,所以必须在synchronized语句块中使用。synchronized关键字用来保护共享资源,阻止其它线程对共享资源的存取,但是这样就会使程序很不灵活。如何才能让当前线程还没有退出synchronized的时候,能够让其它线程进行对共享资源进行访问呢,这三个方法就会让你的程序灵活起来
wait()方法使当前线程暂停执行并释放对象锁标志,让其它线程进入synchronized数据块,当前线程被放入对象等待池中,当调用notify()方法后,将会有任意一个线程被移回锁标志等待池中。notifyAll()方法将从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。
notify():唤醒此对象监视器上的单个线程。
notifyAll():唤醒此对象监视器上的所有线程。
wait():让当前线程处于阻塞状态,直到其它线程调用此对象的notify()或notifyAll()方法,当前线程被唤醒。
wait(long timeout) :让当前线程处于阻塞状态,直到其它线程调用此对象的notify()或notifyAll()方法,或者超出指定的时间等待量,当前线程被唤醒。
notify()测试代码如下:
package sleepandwait; public class MyThread extends Thread{ public MyThread(String name){ super(name); } public void run(){ synchronized(this){ System.out.println(Thread.currentThread().getName()+"等待唤醒..."); System.out.println("我是线程"+ Thread.currentThread().getName()+":我被call notify!"); //唤醒当前线程的wait()等待 notify(); } } }
package sleepandwait; public class TestNotify { public static void main(String[] args) { MyThread t1 = new MyThread("t1线程"); synchronized(t1){ try{ System.out.println(Thread.currentThread().getName()+" start..."); t1.start(); System.out.println(Thread.currentThread().getName()+" wait!"); //t1线程进入等待状态 t1.wait(); System.out.println(Thread.currentThread().getName()+" continue..."); }catch(Exception e){ e.printStackTrace(); } } } }
notifyAll()测试代码:
package sleepandwait; public class TestnotifyAll { private static Object obj = new Object(); public static void main(String[] args) { Thread t1 = new ThreadA("t1"); Thread t2 = new ThreadA("t2"); Thread t3 = new ThreadA("t3"); t1.start(); t2.start(); t3.start(); try { System.out.println(Thread.currentThread().getName()+" sleep3000"); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(obj){ //主线程等待唤醒 System.out.println(Thread.currentThread().getName()+"notifyAll."); obj.notifyAll(); } } static class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public void run(){ synchronized(obj){ try{ System.out.println(Thread.currentThread().getName()+"wait!"); //唤醒当前线程的wait等待 obj.wait(); System.out.println(Thread.currentThread().getName()+" continue!"); }catch(InterruptedException e){ e.printStackTrace(); } } } } }
版权声明:本文为博主原创文章,未经博主允许不得转载。