两个线程输出1A 2B 3C 4D 5E 6F.....

两个线程输出1A 2B 3C 4D 5E 6F…下面介绍四种实现方式:

LockSupport (最简单方式)

代码:

public class LockSupportDemo1 {
    static Thread t1;
    static Thread t2;
    
    public static void main(String[] args) {
        char[] nums = "123456".toCharArray();
        char[] zimos = "ABCDEF".toCharArray();
        t1 = new Thread(()->{
            for (char c: nums){
                System.out.print(c);
                //叫醒T2
                LockSupport.unpark(t2);
                //阻塞T1
                LockSupport.park();
            }
        },"t1");

        t2 = new Thread(()->{
            for (char c: zimos){
                //阻塞T2
                LockSupport.park();
                System.out.print(c);
                //叫醒T1
                LockSupport.unpark(t1);

            }
        },"t2");

        t1.start();;
        t2.start();
    }
}

wait notify方式

public class SyncWaitNotifyDemo1 {
    public static void main(String[] args) {
        final Object object = new Object();
        //保证现场执行顺序
        CountDownLatch countDownLatch = new CountDownLatch(1);
        char[] nums = "123456".toCharArray();
        char[] zimos = "ABCDEF".toCharArray();

        new Thread(()->{
            try {
                //该线程阻塞
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (object){
                for (char c : zimos){
                    System.out.print(c);

                    try {
                        object.notify();
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                object.notify();
            }
        },"t2").start();


        new Thread(()->{

            synchronized (object){
                for (char c : nums){
                    System.out.print(c);
                    //叫醒上面的线程
                    countDownLatch.countDown();
                    try {
                        object.notify();
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                object.notify();
            }
        },"t1").start();
        
    }
}

说明:

wait() 将线程加入到等到队列,notify()将在等待队列中随机挑选一个线程执行。
notify不能叫醒指定的线程,只能随机挑选,notifyAll() 叫醒所有等待线程,大家公抢这把锁

Lock Condition方式

public class ReentrantLockDemo3 {
    public static void main(String[] args) {
        char[] nums = "123456".toCharArray();
        char[] zimos = "ABCDEF".toCharArray();
        Lock lock = new ReentrantLock();
        //理解为队列
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        new Thread(()->{
            try{
                lock.lock();
                for (char c : nums){
                    System.out.print(c);
                    //叫醒对方
                    condition2.signal();
                    condition1.await();
                }
                condition2.signal();
            }catch (InterruptedException e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        },"t1").start();


        new Thread(()->{
            try{
                lock.lock();
                for (char c : zimos){
                    System.out.print(c);
                    //叫醒对方
                    condition1.signal();
                    condition2.await();
                }
                condition1.signal();
            }catch (InterruptedException e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }

        },"t2").start();
    }
}

说明:

这里Condition翻译是条件,可以理解为队列,每个线程对应一个Condition。使用signal()唤醒指定线程,await()让指定线程阻塞。
notify不能叫醒指定的线程,使用Lock Condition可以叫醒指定的线程。

TransferQueue(同步队列)方式

public class TransferQueueDemo1 {
    public static void main(String[] args) {
        char[] nums = "123456".toCharArray();
        char[] zimos = "ABCDEF".toCharArray();

        TransferQueue<Character> transferQueue = new LinkedTransferQueue<Character>();
        new Thread(()->{
            try{
                for (char c : nums){
                    //take获取队列数据,阻塞
                    System.out.print(transferQueue.take());
                    //把当前字符装机队列中  阻塞
                    transferQueue.transfer(c);
                }

            }catch (InterruptedException e){
                e.printStackTrace();
            }
        },"t1").start();


        new Thread(()->{
            try{

                for (char c : zimos){
                    transferQueue.transfer(c);
                    System.out.print(transferQueue.take());

                }

            }catch (InterruptedException e){
                e.printStackTrace();
            }

        },"t2").start();
    }
}

说明:

TransferQueue使用场景在自定义线程池中比较多。它的原理如下图:

两个线程输出1A 2B 3C 4D 5E 6F....._第1张图片
transfer()将一个元素添加到队列中,它是一个阻塞方法,直到被另一个线程消费。
take()方法 也是一个阻塞方法,获取一个元素
所以:TransferQueue队列是一个“手拉手队列”,队列中的长度为0。

你可能感兴趣的:(java)