• Lock+Condition 相对于 wait+notify 的一个优势案例分析


    问题的描述

    启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15. 接着再由线程1打印16,17,18,19,20....以此类推, 直到打印到45.

    wait+notify实现:

    package com.tonyluis;
    public class NumberPrintDemo {
    	static int n = 1;
    	static int state = 0;
    	public static void main(String[] args) {
    		new Thread(new MyThread(0)).start();
    		new Thread(new MyThread(1)).start();
    		new Thread(new MyThread(2)).start();
    	}
    }
    
    class MyThread implements Runnable{
    	private int state;
    	MyThread(){
    		this(0);
    	}
    	MyThread(int state){
    		this.state=state;
    	}
    	public void run() {
    		String threadName=Thread.currentThread().getName();
    		for (int i = 0; i < 3; i++) {
    			synchronized (MyThread.class) {
    				while (state != NumberPrintDemo.state)
    					try {
    						MyThread.class.wait();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				for (int j = 0; j < 5; j++)
    					System.out.println(threadName+ ": " + NumberPrintDemo.n++);
    				System.out.println();
    				NumberPrintDemo.state++;
    				NumberPrintDemo.state%=3;
    				MyThread.class.notifyAll();
    			}
    		}
    	}
    }
    

     Lock+condition实现:

    package com.tonyluis;
    import java.util.concurrent.locks.*;
    public class NumberPrint {
    	static int state = 0;
    	static int n = 1;
    	static Lock lock = new ReentrantLock();
    	static Condition condition[]=new Condition[3];
    	public static void main(String[] args) {
    		for(int i=0;i<condition.length;i++)
    			condition[i]=lock.newCondition();
    		NumberPrint np=new NumberPrint();
    		
    		new Thread(np.new MyThread(0)).start();
    		new Thread(np.new MyThread(1)).start();
    		new Thread(np.new MyThread(2)).start();
    	}
    
    class MyThread implements Runnable{
    	private int state;
    	MyThread(){
    		this(0);
    	}
    	MyThread(int state){
    		this.state=state;
    	}
    	public void run() {
    		String threadName=Thread.currentThread().getName();
    		for (int i = 0; i < 7; i++) {
    			//不需要放到finnally{}中释放锁,因为后面await()会释放锁
    				NumberPrint.lock.lock();
    				while (state != NumberPrint.state)
    					try {
    						NumberPrint.condition[state].await();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				for (int j = 0; j < 5; j++)
    					System.out.println(threadName+ ": " + NumberPrint.n++);
    				System.out.println();
    				NumberPrint.state++;
    				NumberPrint.state%=NumberPrint.condition.length;
    				NumberPrint.condition[NumberPrint.state].signal();
    				try {
    					NumberPrint.condition[state].await();
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    }
    

    使用wait+notify的实现方式,在线程0进入notifyAll()方法之后,会唤醒线程1和线程2,线程1和线程2以及线程0会展开竞争,虽然最终是由线程1获得琐,过程可能比较曲折。

    使用lock+condition的实现方法,线程0只会唤醒线程1,同时进入await()方法释放锁,这样只有线程1能够执行,非常的精确,尤其是并发量比较大的情况下。

  • 相关阅读:
    xml基础一
    FileStream
    串口、COM口、RS232、RS485、USB区别
    DotNet知识点五
    DotNet知识点四
    DotNet知识点三
    DotNet知识点二
    day02 关键字、添加注释、标识符、常量、变量、变量的定义、变量定义注意事项、转义字符
    day01
    22_Map集合(重点)
  • 原文地址:https://www.cnblogs.com/tonyluis/p/5581560.html
Copyright © 2020-2023  润新知