线程sleep、wait、yield、join、notify、notifyAll 以及queue

 1、sleep()方法
       在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。sleep()使当前线程进入阻塞状态,在指定时间内不会执行,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
    2、join方法
等待该线程终止。等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。
    publicclass Test {
        publicstaticvoid main(String[] args) {
                Thread t1 = new MyThread1();
                t1.start(); 

                for (int i = 0; i < 20; i++) {
                        System.out.println("主线程第" + i +"次执行!");
                        if (i > 2)try { 
                                //t1线程合并到主线程中,主线程停止执行过程,转而执行t1线程,直到t1执行完毕后继续。
                                t1.join(); 
                        } catch (InterruptedException e) {
                                e.printStackTrace(); 
                        } 
                } 
        } 

class MyThread1 extends Thread { 
        publicvoid run() {
                for (int i = 0; i < 10; i++) {
                        System.out.println("线程1第" + i + "次执行!");
                } 
        } 
}
     3、yield方法
        该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
     4、wait()方法
        wait()方法使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块,当前线程被放入对象等待池中。当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。
wait()方法释放锁、notify()不释放锁
        notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。
使用wait和 notify实现线程之间的通信,代码如下:
public class CountDownLatchClass {
	private volatile static List list = new ArrayList<>();
	
	public void add() {
		list.add("abc");
		
	}
	
	public int size(){
		return list.size();
	}
	
	
	public static void main(String[] args) {
		final CountDownLatchClass list = new CountDownLatchClass();
		
		final Object lock = new Object();
		
		Thread t1 = new Thread(new Runnable() {
			public void run() {
				try{
					synchronized (lock) {
					for(int i = 0; i<10; i++){
						list.add();
						System.out.println("当前线程:"+ Thread.currentThread().getName()+"添加了一个元素");
						Thread.sleep(500);
						if(list.size()==5){
							System.out.println("已经发出通知。。。。");
							lock.notify();
						}
					}
					}
				}catch(InterruptedException e){
					e.printStackTrace();
				}
			}
		},"t1");
		
		Thread t2 = new Thread(new Runnable() {
			public void run() {
				 synchronized (lock) {
				if (list.size() != 5) {
					try {
						
						System.out.println("t2进入。。。。");
						 lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("当前线程:"+ Thread.currentThread().getName()+"收到线程停止.....");
				throw new RuntimeException();
				 }
			}
		},"t2");
		
		t2.start();
		t1.start();
	}

	
}
输出如下:
t2进入。。。。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已经发出通知。。。。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t2收到线程停止.....
Exception in thread "t2" java.lang.RuntimeException
at com.hundsun.base.thread.safeornot.CountDownLatchClass$2.run(CountDownLatchClass.java:59)
at java.lang.Thread.run(Unknown Source)

该方法的实现的缺点:只有当t1运行完之后,t2线程才接收到通知,不具备实时性,可通过CountDownLatch来实现,代码如下:
public class CountDownLatchClass {
	private volatile static List list = new ArrayList<>();
	
	public void add() {
		list.add("abc");
		
	}
	
	public int size(){
		return list.size();
	}
	
	
	public static void main(String[] args) {
		final CountDownLatchClass list = new CountDownLatchClass();
		
		//final Object lock = new Object();
		final CountDownLatch countDownLatch = new CountDownLatch(1);
		
		Thread t1 = new Thread(new Runnable() {
			public void run() {
				try{
					//synchronized (lock) {
					for(int i = 0; i<10; i++){
						list.add();
						System.out.println("当前线程:"+ Thread.currentThread().getName()+"添加了一个元素");
						Thread.sleep(500);
						if(list.size()==5){
							System.out.println("已经发出通知。。。。");
							countDownLatch.countDown();
							//lock.notify();
						}
					}
					//}
				}catch(InterruptedException e){
					e.printStackTrace();
				}
			}
		},"t1");
		
		Thread t2 = new Thread(new Runnable() {
			public void run() {
				// synchronized (lock) {
				if (list.size() != 5) {
					try {
						
						System.out.println("t2进入。。。。");
						// lock.wait();
						countDownLatch.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("当前线程:"+ Thread.currentThread().getName()+"收到线程停止.....");
				throw new RuntimeException();
				// }
			}
		},"t2");
		
		t2.start();
		t1.start();
	}

	
}
输出如下:
t2进入。。。。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已经发出通知。。。。
Exception in thread "t2" 当前线程:t2收到线程停止.....
当前线程:t1添加了一个元素
java.lang.RuntimeException
at com.hundsun.base.thread.safeornot.CountDownLatchClass$2.run(CountDownLatchClass.java:62)
at java.lang.Thread.run(Unknown Source)
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素

5、通过wait和notify实现queue。
如果队列中没有元素,调用take方法时,则调用此方法的线程被阻塞,直到队列中有数据被加入
实现代码如下:
public class QueueClass {

	//1、需要一个装元素的集合
	private final LinkedList<Object> list = new LinkedList<Object>();
	//2、需要一个计数器
	private final AtomicInteger count = new AtomicInteger(0);
	//3、需要制定上限和下限
	private final int maxSize;
	private final int minSize = 0;
	
	private final Object lock = new Object();
	
	public QueueClass (int maxSize){
		this.maxSize = maxSize;
	}

	public void put (Object obj) {
		synchronized(lock){
			while(count.get() == maxSize){
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//加入元素
			list.add(obj);
			//计数器加
			count.getAndIncrement();
			System.out.println(" 元素 " + obj + " 被添加 ");
			//通知另外一个线程(唤醒)
			lock.notify();
			
		}
	}
	
	public Object take(){
		Object temp = null;
		synchronized (lock) {
			while(count.get() == minSize){
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			//移除元素
			temp = list.removeFirst();
			//计数器递减
			count.getAndDecrement();
			System.out.println(" 元素 " + temp + " 被消费 ");
			//唤醒另外一个线程
			lock.notify();
		}
		return temp;
	}
	
	public int size(){
		return count.get();
	}
	
	
	public static void main(String[] args) throws Exception {
		
		final QueueClass m = new QueueClass(5);
		m.put("a");
		m.put("b");
		m.put("c");
		m.put("d");
		m.put("e");
		System.out.println("当前元素个数:" + m.size());
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				m.put("h");
				m.put("i");
			}
		}, "t1");
		
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
					Object t1 = m.take();
					//System.out.println("被取走的元素为:" + t1);
					Thread.sleep(1000);
					Object t2 = m.take();
					//System.out.println("被取走的元素为:" + t2);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "t2");

		t1.start();
		Thread.sleep(1000);
		t2.start();
		
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值