线程中的等待与唤醒

上一篇文章讲到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();
				}
			}
		}
	}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 02:36:12

线程中的等待与唤醒的相关文章

JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是class对象 我们在上节验证了同步函数的锁是this,但是对于静态同步函数,你又知道多少呢? 我们做一个这样的小实验,我们给show方法加上static关键字去修饰 private static synchronized void show() { if (tick > 0) { try { Thread

线程间通讯(等待唤醒机制)

锁.whit(); //将线程丢进线程池,暂停运行. 锁.notify(); //唤醒线程池中的最先存入那个同锁线程 锁.notifyAll(); //唤醒线程池中所有的同锁线程 都使用在同步中,因为要对持有监视器(锁)的线程操作.所以要使用在同步中,因为只有同步才具有锁. 为什么这些操作线程的方法要定义Object类中因为这些方法在操作同步中线程时,都需要标识它们所操作线程持有的锁只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒.不可以对不同锁中的线程进行唤醒. 也就是说,等待和唤

Java多线程5:线程等待与唤醒

原文:http://www.cnblogs.com/skywang12345/p/3479224.html wait(),notify(), notifyAll()等方法介绍在Object.java中,定义了wait(),notify()和notifyAll()等方法.wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁.而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程:notify()是唤醒单个线程,而notifyAll()

java 多线程—— 线程等待与唤醒

java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 java 多线程—— 线程等待与唤醒 概述 第1部分 wait(), notify(), notifyAll()等方法介绍 第2部分 wait()和notify()示例 第3部分 wait(long timeout)和notify() 第4部分 wait() 和 notifyAll() 第5部分 

Java多线程系列---“基础篇”05之 线程等待与唤醒

转自:https://www.cnblogs.com/skywang12345/p/3479224.html  (含部分修改) 概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括: wait(), notify(), notifyAll()等方法介绍 wait()和notify() wait(long timeout)和notify() wait() 和 notifyAll() 为什么notify(), wait()等函数定义在Object中,而不是Thread中 一. wait(),

多线程之Java中的等待唤醒机制

多线程的问题中的经典问题是生产者和消费者的问题,就是如何让线程有序的进行执行,获取CPU执行时间片的过程是随机的,如何能够让线程有序的进行,Java中提供了等待唤醒机制很好的解决了这个问题! 生产者消费者经典的线程中的问题其实是解决线程中的通讯问题,就是不同种类的线程针对同一资源的操作,这里其实有一张图很好的阐述了这其中的问题: 1 //代码中的实体类 2 public class Student { 3 String name; 4 int age; 5 boolean flag; // 默认

18、多线程 (线程安全、线程同步、等待唤醒机制、单例设计模式)

线程操作共享数据的安全问题 *A:线程操作共享数据的安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码. 程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. 售票的案例 *A:售票的案例 /* - 多线程并发访问同一个数据资源 - 3个线程,对一个票资源,出售 */ public class ThreadDemo { public static void main(String[] args) { //创建Runnable接口实现

Java线程的等待与唤醒

生产者和消费者必须使用同步代码块包裹起来,保证等待和唤醒只能有一个执行,同步使用的锁对象必须保证唯一 Thread中重要方法 void wait() 在其他线程调用此对象的notify()方法或notifyall()方法前,导致当前线程等待 void notify() 唤醒在此对象监视器上等待的单个线程后,会继续执行wait方法之后的代码 void notifyAll() 唤醒所有等待线程 void wait(long m)在毫秒结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到R

Java 中的等待唤醒机制透彻讲解

线程的状态 首先了解一下什么是线程的状态,线程状态就是当线程被创建(new),并且启动(start)后,它不是一启动就进入了执行状态(run),也不是一直都处于执行状态. 这里说一下Java 的Thread类里面有一个State方法,这个方法里面涵盖了6种线程的状态,如下: public enum State { // 尚未启动的线程的线程状态. NEW, // 可运行线程的线程状态. RUNNABLE, // 线程的线程状态被阻塞,等待监视器锁定. BLOCKED, // 等待线程的线程状态.