日常记录——多线程与高并发—交替打印数字与字母,交替输出1A2B3C4D...26Z

一、介绍

用两个线程,一个输出字母,一个输出数字,交替输出1A2B3C4D…26Z。
实现逻辑:使用控制方法,控制两个线程交替按顺序打印。

二、实现代码

1.synchronized+wait+notify:依赖对象的锁的原理,wait将线程放入等待池,notify唤醒锁资源竞争的线程放入锁池,在对象锁池的才有资格竞争锁资源。

    static  int num = 1;//从1开始
    static char word = 'A';//从A开始
    public static void main(String[] args) {
    	//对象锁
        Object o = new Object();
        new Thread(() -> {
            synchronized (o){
                while (num<27){
                    System.out.print(num);
                    num ++;
                    try {
                    	//唤醒另一线程
                        o.notify();
                        //阻塞本线程
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //为了线程运行结束   不加  则最后执行的是o.wait();  一直在等待池
                o.notify();
            }
        }).start();
        new Thread(() -> {
            synchronized (o){
                while ('Z' >= word){
                    try {
                        System.out.print(word);
                        word = (char)(word+1);
                        //唤醒另一线程
                        o.notify();
                        //阻塞本线程
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //为了线程运行结束   不加  则最后执行的是o.wait();  一直在等待池
                o.notify();
            }
        }).start();
    }

2.ReentrantLock+Condition :依赖等待队列,条件队列,ReentrantLock维护等待队列,Condition维护条件队列,await将线程放入条件队列,signal方法从条件队列获取一个线程放入等待队列,只有等待队列的线程才有资格竞争锁资源。

	static  int num = 1;
    static char word = 'A';
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        //创建两个 Condition(条件队列)  管理 两个线程  
        Condition t1 = lock.newCondition();
        Condition t2 = lock.newCondition();
        new Thread(() -> {
            try {
            	//加锁
                lock.lock();
                while (num<27){
                    System.out.print(num);
                    num ++;
                    //唤醒另一线程
                    t2.signal();
                    //阻塞当前线程
                    t1.await();
                }
                //为了线程运行结束   不加  另一线程一直在条件队列
                t2.signal();
            }catch (InterruptedException e){
                e.printStackTrace();
            }finally {
            	//释放锁
                lock.unlock();
            }

        }).start();
        new Thread(() -> {
            try {
                lock.lock();
                while ('Z' >= word){
                    System.out.print(word);
                    word = (char)(word+1);
                    //唤醒另一线程
                    t1.signal();
                    //阻塞当前线程
                    t2.await();
                }
                //为了线程运行结束   不加  另一线程一直在条件队列
                t1.signal();
            }catch (InterruptedException e){
                e.printStackTrace();
            }finally {
            	//释放锁
                lock.unlock();
            }
        }).start();

    }

3.无锁+自旋+volatile:依赖volatile的线程可见性(MESI、读写屏障),自旋根据标志值执行打印。

	static  int num = 1;
    static char word = 'A';
    //创建线程可见标志
    static volatile boolean flag = true;
    public static void main(String[] args) {
        Object o = new Object();
        new Thread(() -> {
        	//外层打印次数
            while (num<27){
            	//内层flag为true 打印数字
                while(flag){
                    System.out.print(num);
                    num ++;
                    //更新 flag 值为 false  另一线程打印
                    flag = false;
                }
            }
        }).start();
        new Thread(() -> {
        	//外层打印次数
            while ('Z' >= word){
            	//内层flag为false打印字母
                while(!flag){
                    System.out.print(word);
                    word = (char)(word+1);
                    //更新 flag 值为 true  另一线程打印
                    flag = true;
                }
            }
        }).start();
    }

4.LockSupport:基于UNSAFE类的操作,可指定唤醒线程。

	static  int num = 1;
    static char word = 'A';
    //声明两个线程
    static Thread t1 , t2;
    public static void main(String[] args) {
        t1 = new Thread(() -> {
            while (num<27){
                System.out.print(num);
                num ++;
                //唤醒t2线程
                LockSupport.unpark(t2);
                //阻塞当前线程
                LockSupport.park();
            }
        });
        t2 = new Thread(() -> {
            while ('Z' >= word){
            	 //阻塞当前线程 保证数字先输出
                LockSupport.park();
                System.out.print(word);
                word = (char)(word+1);
                //唤醒t1线程
                LockSupport.unpark(t1);
            }
        });
        t1.start();
        t2.start();
    }

5.ArrayBlockingQueue:基于阻塞队列容量原理,入队时容量满阻塞,出队时容量为0阻塞。

static  int num = 1;
    static char word = 'A';
    public static void main(String[] args) {
    	//两容量为1的阻塞队列  结合使用控制两个线程
        BlockingQueue t1 = new ArrayBlockingQueue(1);
        BlockingQueue t2 = new ArrayBlockingQueue(1);
        new Thread(() -> {
            while (num<27){
                try {	
                	//保证数字先打印
                    System.out.print(num);
                    num ++;
                    //入队 如果超过容量阻塞当前线程
                    t1.put("t1");
                    //出队 如果容量为空阻塞当前线程
                    t2.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();
        new Thread(() -> {
            while ('Z' >= word){
                try {
                	 //出队 如果容量为空阻塞当前线程  刚开始执行肯定阻塞  因为没入队
                    t1.take();
                    System.out.print(word);
                    word = (char)(word+1);
                    //入队 如果超过容量阻塞当前线程
                    t2.put("t2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

6.SynchronousQueue: 依赖无容量原理,take和put必须成对出现,单独put阻塞,单独take阻塞,put之后阻塞 take后 唤醒。

	static  int num = 1;
    static char word = 'A';
    public static void main(String[] args) {
        SynchronousQueue print = new SynchronousQueue();
        new Thread(() -> {
            while (num<27){
                try {
                	//将数字入队 然后阻塞  等待 出队打印 唤醒
                    print.put(num);
                    num ++;
                     //出队打印 唤醒 另一线程
                    System.out.print(print.take());

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

            }
        }).start();
            new Thread(() -> {
            while ('Z' >= word){
                try {
                	//出队打印 唤醒 另一线程
                    System.out.print(print.take());
                     //将字符入队 然后阻塞  等待 出队打印 唤醒
                    print.put(word);
                    word = (char)(word+1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

7.TransferQueue:依赖transfer方法入队元素,必须出队,当前线程才可继续执行。

 static  int num = 1;
    static char word = 'A';
    public static void main(String[] args) {
        TransferQueue print = new LinkedTransferQueue();
        new Thread(() -> {
            while (num<27){
                try {
                	//将数字入队 然后阻塞  等待 出队打印 唤醒
                    print.transfer(num);
                    num ++;
                    //出队打印 唤醒 另一线程
                    System.out.print(print.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();
        new Thread(() -> {
            while ('Z' >= word){
                try {
                	//出队打印 唤醒 另一线程
                    System.out.print(print.take());
                    //将字符入队 然后阻塞  等待 出队打印 唤醒
                    print.transfer(word);
                    word = (char)(word+1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

你可能感兴趣的:(多线程与高并发,队列,多线程,java,并发编程,字符串)