并发

两个线程循环打印数字字母的问题

2020-05-05  本文已影响0人  gigglesoso

一道经典的多线程面试题:

两个线程,一个线程打印1-26,另一个线程打印A-Z,但是需要的效果是两个线程交替打印,产生效果如1A2B………26Z的效果。

思路如下:需要实现两个线程,重写run方法,run方法内部需要26次for循环,分别打印数字和字母,但是需要线程1(打印1)阻塞,切换到线程2(打印A)阻塞,切换到线程1(打印2)……

package demo;


/**
 * 循环打印1A2B……
 * @author Gxp
 *
 */
public class A1B2_syn {
    // 定义一个锁
    static Object lock = new Object();
    // 定义两个线程
    static Thread number = new Thread(()->{
        // 线程内部方法需要加synchronized,锁定lock对象
        synchronized (lock) {
            for (int i = 1; i < 27; i++) {
                System.out.print(i);
                // 打印出一个后,先唤醒其他线程
                lock.notifyAll();
                try {
                    // 阻塞当前线程,并且释放锁,这里判断是最后的边界条件,最后一次输出当前线程就不需要阻塞了
                    if (i != 25) {
                        lock.wait();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    });
    
    static Thread letter = new Thread(()->{
        synchronized (lock) {
            for (int i = 0; i < 26; i++) {
                System.out.print((char)('A'+i));
                lock.notifyAll();
                try {
                    // 这里一定要判断边界条件,假如是最后一个输出,则不需要阻塞,直接结束就好了,否则该线程会一直阻塞
                    if (i != 25) {
                        lock.wait();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    });
    
    
    public static void main(String[] args) {
        number.start();
        // 保证线程letter线程先运行
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        letter.start();
    }
}

package demo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 循环打印1A2B……  使用lock实现
 * @author Gxp
 *
 */
public class A1B2_lock {
    
    static Lock lock = new ReentrantLock();
    static Condition letter = lock.newCondition();
    static Condition number = lock.newCondition();
    
    static Thread numberThread = new Thread(()->{
        try {
            lock.lock();
            for (int i = 0; i < 26; i++) {
                System.out.print(i+1);
                // 需要先唤醒letter线程
                letter.signal();
                // 然后再阻塞自己
                if (i != 25) {
                    number.await();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    });
    
    
    static Thread letterThread = new Thread(()->{
        try {
            lock.lock();
            for (int i = 0; i < 26; i++) {
                System.out.print((char)('A'+i));
                number.signal();
                if (i != 25) {
                    letter.await();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    });
    
    public static void main(String[] args) {
        numberThread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        letterThread.start();
    }
}


上一篇下一篇

猜你喜欢

热点阅读