写两个线程,其中一个输出打印1-52,另一个打印A-Z,打印顺序为12A34B56C78D...5152Z

这是一个常见的笔试题,自己本身对多线程理解的不是很透彻,特此记录一下这种多线程面试题下面通过两种方式实现。

第一种方式通过Lock锁机制来实现:

package com.zte.st.dailybuild.controller;

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

/**
 * Created by 6092002943 on 2019/7/23.
 */
public class ThreadTest1 {

     int i = 0;
    int zm = 65;
    boolean flag = true;

    private Lock lock = new ReentrantLock();
    private Condition cd1 = lock.newCondition();
    private Condition cd2 = lock.newCondition();

    public void printNum() {

        lock.lock();//上锁
        try {
            System.out.print("数字前 ");
            while (!flag) {
                cd1.await();//把当前线程阻塞挂起
                System.out.print("数字wait后 ");
            }
            System.out.print("数字后 ");
            System.out.print(++i);
            System.out.print(++i);
            flag = false;
            cd2.signal();//唤醒阻塞的线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//释放锁,必须在finally中去释放,避免死锁
        }
    }

    public void printZIMU() {

        lock.lock();

        try {
            System.out.print("ZIMU前 ");
            while (flag) {
                cd2.await();//阻塞
                System.out.print("字母wait后 ");
            }
            System.out.print("ZIMU后 ")                                                                                                              ;
            flag = true;
            System.out.print(Character.toChars(zm));
            zm++;
            cd1.signal();//唤醒阻塞线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {

        ThreadTest1 test = new ThreadTest1();
        new Thread(() -> {
            for (int i = 0; i < 26; i++) {
                test.printNum();
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 0; i < 26; i++) {
                test.printZIMU();
            }
        }, "BB").start();

    }

}

运行结果:

 

12A34B56C78D910E1112F1314G1516H1718I1920J2122K2324L2526M2728N2930O3132P3334Q3536R3738S3940T4142U4344V4546W4748X4950Y5152Z

 发现: cd2.signal(); 表示唤醒阻塞的线程,即回到await()方法阻塞之后接着执行,每个方法每次执行都会执行两次,这个两次指的是flag变化两次。

第二种使用wait、notify:

package com.zte.st.dailybuild.controller;

import org.springframework.context.event.GenericApplicationListener;

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

/**
 * Created by 6092002943 on 2019/7/22.
 */
public class ThreadTest {
    
    public static void main(String[] args) {
        ThreadTest test = new ThreadTest();
        new Thread(() -> {
            for (int i = 0; i < 1; i++) {
                test.writeChars();
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 0; i < 1; i++) {
                test.writeNums();
            }
        }, "BB").start();


    }

    private boolean flag = false;

    public synchronized void writeNums() {

        try {

            for (int i = 1; i <= 26; ) {
                System.out.print("数字前 ");
                if (flag) {
                    System.out.print("数字wait前 ");
                    wait();
                    System.out.print("数字wait后 ");
                } else {
                    System.out.print(i * 2 - 1);
                    System.out.print(i * 2);
                    flag = true;
                    i++;
                    this.notifyAll();
                    System.out.print("数字后 ");

                }

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

    public synchronized void writeChars() {
        try {
            for (int i = 'A'; i <= 'Z'; ) {
                System.out.print("字符前  ");
                if (!flag) {
                    System.out.print("字符wait前 ");
                    wait();
                    System.out.print("字符wait后 ");
                } else {
                    System.out.print((char) i);
                    flag = false;
                    i++;
                    this.notifyAll();
                    System.out.print("字符后 ");
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


 结果:和第一种结果是一样的!可以自己去试。

总结:好多家公司的笔试题都有这种类似的,特此记录一下,研究一下,基础横重要的。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值