Java小题目之两个线程顺序打印A、B

来源:互联网 发布:巡店软件 编辑:程序博客网 时间:2024/06/06 04:43

1、问题描述

使用Java多线程方式来实现循环打印A、B,并保证不乱序。

2、解决方案

java在编写多线程程序时,为了保证线程安全,需要对数据同步,经常用到两种同步方式就是Synchronized和重入锁ReentrantLock。

  1. 利用synchronized关键字来实现
package org.ibenben.test;public class OrderThreadTest {    public static void main(String[] args){        OrderThreadTest test = new OrderThreadTest();        Object lock = new Object();        test.new Output(lock, "A").start();        test.new Output(lock, "B").start();    }    class Output extends Thread{        private Object lock;        private String value;        public Output(Object lock,String value) {            this.lock = lock;            this.value = value;        }        @Override        public void run() {            synchronized (lock) {                while (true) {                                                  try {                        System.out.println(value);                        lock.notifyAll();                        lock.wait();                                                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }           }           }}

2.使用ReentrantLock来实现

package org.ibenben.test;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;public class OrderThreadTest {    private ReentrantLock lock = new ReentrantLock();    Condition aCondition = lock.newCondition();    Condition bCondition = lock.newCondition();    public static void main(String[] args){        OrderThreadTest test = new OrderThreadTest();        test.new AOutput().start();        test.new BOutput().start();    }    class AOutput extends Thread{        @Override        public void run() {            while (true) {                                              try {                    lock.lock();                    System.out.println("A");                    bCondition.signal();                    aCondition.await();                 } catch (InterruptedException e) {                    e.printStackTrace();                }finally {                    lock.unlock();                }            }           }       }    class BOutput extends Thread{        @Override        public void run() {            while (true) {                                              try {                    lock.lock();                    System.out.println("B");                    aCondition.signal();                    bCondition.await();                 } catch (InterruptedException e) {                    e.printStackTrace();                }finally {                    lock.unlock();                }            }        }       }}

3、Synchronized与ReentrantLock

ReentrantLock与synchronized关键字一样,属于互斥锁,synchronized中的锁是非公平的(公平锁是指多个线程等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁),ReentrantLock默认情况下也是非公平的,但可以通过带布尔值的构造函数要求使用公平锁。线程通过ReentrantLock的lock()方法获得锁,用unlock()方法释放锁。

ReentrantLock和synchronized关键字的区别

  1. ReentrantLock在等待锁时可以使用lockInterruptibly()方法选择中断, 改为处理其他事情,而synchronized关键字,线程需要一直等待下去。同样的,tryLock()方法可以设置超时时间,用于在超时时间内一直获取不到锁时进行中断。
  2. ReentrantLock可以实现公平锁,而synchronized的锁是非公平的。
  3. ReentrantLock拥有方便的方法用于获取正在等待锁的线程。
  4. ReentrantLock可以同时绑定多个Condition对象,而synchronized中,锁对象的wait()和notify()或notifyAll()方法可以实现一个隐含的条件,如果要和多于一个条件关联时,只能再加一个额外的锁,而ReentrantLock只需要多次调用newCondition方法即可。

性能比较
在JDK1.6之前,ReentrantLock的性能要明显优于synchronized,但是JDK1.6中加入了很多针对锁的优化措施,synchronized和ReentrantLock的性能基本完全持平了。

ReentrantLock缺点
ReentrantLock的主要缺点是方法需要置于try-finally块中,另外,开发人员需要负责获取和释放锁,而开发人员常常忘记在finally中释放锁。

阅读全文
0 0