synchronized keyword, Lock objects blocking queue issues

A. You talk about synchronized and lock What is the difference?

1.synchronized is java keywords belong jvm level, the underlying objects are achieved by moninter .Lock is specific interface, belong api level.

2.synchronized does not require the user to manually release the lock, when the code is executed synchronized completed, the system will automatically release the thread lock occupation, Lock

The user is required to manually release the lock, if not take the initiative to release the lock, it will lead to deadlock.

3.synchronized not be interrupted, unless the program is finished or thrown .Lock can be interrupted (1. Set the time-out method tryLock () 2.lockInterruptibly ()

Put the code block, invoke interrupt () interruptible)

4.synchronized non fair lock is unfair Lock Lock default, but can be configured to process pass Boolean value to determine the type of lock. (True lock fair, fair to false non-lock)

5.synchronized not bound multiple conditions, Lock can be grouped need to wake up wake up the thread, accurate wake, rather than random synchronized as a wake-up thread

Either all wake up.

 

Case: achieving accurate calls between multiple threads (to achieve A-> B-> C starts between the three threads),

Examples of synchronized lock superior

Requirements: A printing thread 5, B printing thread 10, C 15 thread printing, followed by printing at 5 A

Print B 10, C 15 print. Loop is executed 10 times

class ShareResource {
     Private  int NUM = 1; // Flag A indicates a thread of execution, B 2 represents a thread of execution, a thread of execution 3 represents C 
    Private Lock Lock = new new of ReentrantLock ();
     Private for condition Condition lock.newCondition C1 = (); / / A thread of execution conditions 
    Private for condition condition lock.newCondition C2 = (); // B thread of execution conditions 
    Private for condition condition lock.newCondition C3 = (); // C thread of execution conditions 

    public  void print5 () { 
        Lock.lock (); 
        the try {
             // if not A thread executes 
            the while (NUM! = 1 ) {
                 //A thread waits 
                c1.await (); 
            } 
            // switch to thread B 
            NUM = 2 ;
             // wake-up thread B 
            c2.signal ();
             for ( int I =. 1; I <=. 5; I ++ ) { 
                the System.out. the println (. Thread.currentThread () getName () + "\ T" + I); 
            } 
        } the catch (InterruptedException E) { 
            e.printStackTrace (); 
        } the finally { 
            lock.unlock (); 
        } 
    } 

    public  void  print10 () {
        Lock.lock (); 
        the try {
            while (num != 2){
                c2.await();
            }
            num = 3;
            c3.signal();
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName() + "\t"+i);
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try {
            while (num != 3){
                c3.await();
            }
            num = 1;
            c1.signal();
            for (int i = 1; i <= 15; i++) {
                System.out.println(Thread.currentThread().getName() + "\t"+i);
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }            
 public  static  void main (String [] args) { 
        ShareResource SR = new new ShareResource (); // get the object
         // execution thread 10 A 
        new new the Thread (() -> {
             for ( int I =. 1; I <= 10; ++ I ) { 
                sr.print5 (); 
            } 
        }, "A" ) .start ();
    // execution thread 10 B 
        new new the thread (() -> {
             for ( int I =. 1; I <= 10; I ++ ) { 
                sr.print10 ();  
            }
        }, "B") .start ();
    // execution threads 10 C 
        new new the Thread (() -> {
             for ( int I =. 1; I <= 10; I ++ ) { 
                sr.print15 (); 
            } 
        }, "C" ). Start (); 
    }

Results of the:

 

 A, B, C three threads are executed sequentially without interruption, the result is correct

II. You talk about the producer / consumer model, combined with the business, write a case

Example: a plurality of threads operate simultaneously, producer +1, -1 consumers

1. Lock achieve

class ShareData {
     Private  int Number = 0;    // resource data 
    Private Lock Lock = new new of ReentrantLock (); // lock object 
    Private for condition Condition for condition Condition lock.newCondition = (); // condition 

    / * Manufacturer +1 * / 
    public  void INCREMENT () {   
        Lock.lock (); 
        the try {
             // if the producer is full, you enter the wait state
             // to use while preventing spurious wakeup (jdk1.8 source document can not be used !!! IF) 
            while (Number the ! = 0 ) {
                 // wait 
                Condition.await ();
            } 
            // business logic +1 
            Number The ++ ; 
            System.out.println (. Thread.currentThread () getName () + "\ t" + Number The);
             // wake consumer threads -1 
            condition.signalAll (); 
        } the catch (InterruptedException E) { 
            e.printStackTrace (); 
        } the finally { 
            lock.unlock (); 
        } 
    } 
    / * consumer thread 1 operation * / 
    public  void Decrement () { 
        Lock.lock (); 
        the try {
             // if you have not the resources, number = 0, wait for the producer thread production
            the while (Number The == 0) { 
                Condition.await (); 
            } 
            // business logic -1 
            number The ; 
            System.out.println (Thread.currentThread (). GetName () + "\ T" + Number);
             // wake producer threads 
            condition .signalAll (); 
        } the catch (InterruptedException E) { 
            e.printStackTrace (); 
        } the finally { 
            lock.unlock (); 
        } 
    } 
}
 public static void main(String[] args) {

        ShareData shareData = new ShareData();
        // 生产者
        new Thread(()->{
            for (int i = 1; i <= 5; i++) {
                shareData.increment();
            }
        },"T1").start();

        //消费者
        new Thread(()->{
            for (int i = 1; i <= 5; i++) {
                shareData.decrement();
            }
        },"T2").start();

        
    }

Results of the:

 

 A production, a consumer, generating a consumer a .......

2. Use BlockingQueue achieve

class ShareMessage{
    // 开关,true表示执行,false表示关闭
    private volatile boolean FLAG = true;
    // 原子整型,操作不能被分割
    private AtomicInteger atomicInteger = new AtomicInteger();
    // 阻塞队列,用于存放数据
    private BlockingQueue<String> blockingQueue = null;

    // 初始化BlockingQueue 对象的具体的实现类
    public ShareMessage(BlockingQueue<String> blockingQueue) {
        this.blockingQueue = blockingQueue;
        System.out.println(blockingQueue.getClass().getName());
    }

   /*生产者模型,*/
    public void produce() throws InterruptedException{
        String data = null; 
        boolean retValue ;
        while (FLAG){ // 如果开关打开
             // 等同于 i++ + ""
            data = atomicInteger.incrementAndGet() + "";
            // 把数据放到阻塞队列中,并设置超时的时间
            retValue = blockingQueue.offer(data,2L, TimeUnit.SECONDS);
            // 如果放置成功
            if(retValue){
                System.out.println(Thread.currentThread().getName() + "\t"+ data + "插入队列成功");
            }else {
                System.out.println(Thread.currentThread().getName() + "\t"+ data + "插入队列失败");
            }
             // 让消费者线程取,方便显示
            TimeUnit.SECONDS.sleep(1);
        }
        System.out.println(Thread.currentThread().getName() + "生产结束,FLAG设置为false");

    }
    /*消费者线程*/
    public void consume() throws InterruptedException{
        String res = null;
        while (FLAG){
            // 从阻塞队列中获取数据
            res = blockingQueue.poll(2L,TimeUnit.SECONDS);
            // 如果没有获取到数据,
            if(null == res || res.equalsIgnoreCase("")){
                // 停止生产者线程,并退出当前的消费者线程
                FLAG = false;
                System.out.println(Thread.currentThread().getName()+"\t超过2秒钟没有取到数据,消费退出");
                return;
            }
            System.out.println(Thread.currentThread().getName()+"\t"+res+"消费队列成功");
        }
    }

    /*关闭生产/消费模型*/
    public void stop(){
        this.FLAG = false;
    }

}
public static void main(String[] args) {
        ShareMessage sm = new ShareMessage(new ArrayBlockingQueue<>(10));

        // 启动生产者
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"生产线程启动");
            try {
                sm.produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"produce").start();

        // 启动消费者
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"消费线程启动");
            try {
                sm.consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"consume").start();

       // 执行5秒钟后,停止运行
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sm.stop();
    }

执行结果:

 

j结论:

使用阻塞队列实现生产者/消费者模型更优于使用Lock的方式,因为阻塞队列中不需要手动的去停止/唤醒线程.

 

Guess you like

Origin www.cnblogs.com/luhuajun/p/12130819.html