你应该会的一道多线程笔试题

来源:互联网 发布:淘宝开店要求品牌注册 编辑:程序博客网 时间:2024/05/22 05:10

前言

最近也面了好多家企业,也总结到很多笔试经验和面试经验。笔试大多数Java题目都是牛客网原题和简单排序,数据库,Java基础概念,数据结构,MVC模式等。面试官问的题目涉及的知识无非是Java基础知识,设计模式,网络等。我发现出现频率很高的知识点有多线程,设计模式(单例模式,策略模式,观察者模式)等。今天就来说一下笔试和面试中常见的多线程题目。

dream.jpg

笔试

  • 题目:有ABC三个线程,,A线程输出AB线程输出BC线程输出C,要求,同时启动三个线程,,按顺序输出ABC,循环10次。这道题目出现的频率很高啊。
第一种思路
  • 创建3个线程轮流输出,用lock对象去同步线程的状态,用count变量标识出哪个线程,MAX变量用于边界控制,适时退出轮询。

  • 手写代码

public class PrintABC {    public static void main(String[] args) {        final Lock lock = new ReentrantLock();        Thread a = new Thread(new PrintfABCThread("A", lock, 0));        Thread b = new Thread(new PrintfABCThread("B", lock, 1));        Thread c = new Thread(new PrintfABCThread("C", lock, 2));        a.start();        b.start();        c.start();    }}class PrintfABCThread implements Runnable {    private String name;    private Lock lock;    private Integer flag;    public static int count = 0;    public static final int MAX = 30;    public PrintfABCThread(String name, Lock lock, Integer flag) {        this.name = name;        this.lock = lock;        this.flag = flag;    }    @Override    public void run() {        while (true) {            lock.lock();            if (count >= MAX) {                lock.unlock();                return;            }            if (count % 3 == flag) {                System.out.println(name);                count++;            }            lock.unlock();        }    }}
  • 输出结果
    image.png
第二种思路
  • 通过Thread类的join()方法让我们开启的线程加入到主线程,只有我们开启的新线程结束后,主线程才能继续执行。

  • 手写代码

public class PrintfABC {    public static void main(String[] args) throws InterruptedException {        for (int i = 0; i < 10; i++) {            Thread a = new Thread(new PrintThread("A"));            a.start();            a.join();            Thread b = new Thread(new PrintThread("B"));            b.start();            b.join();            Thread c = new Thread(new PrintThread("C"));            c.start();            c.join();        }    }}class PrintThread implements Runnable {    private String name;    public PrintThread(String name) {        this.name = name;    }    @Override    public void run() {        System.out.println(name);    }}
  • 输出结果
    image.png

  • 第二个题目: 用多线程去处理"abc""def"“ghi”这个三个字符串,让它们以"adg""beh"“cfi”这种形式输出。这个题目之前是红星美凯龙技术部笔试卷的压轴题,分值是20分。
第一种思路

其实跟第一个题目的解决思路是差不多,唯一变的就是我们要获取下标访问字符串从而获取字符。我们可以通过count变量来标识由哪一个线程输出,通过count / 3 获取下标。

public class DemoTwo {    public static void main(String[] args) {        final Lock lock = new ReentrantLock();        Thread a = new Thread(new PrintThread("abc", lock, 0));        Thread b = new Thread(new PrintThread("def", lock, 1));        Thread c = new Thread(new PrintThread("ghi", lock, 2));        a.start();        b.start();        c.start();    }}class PrintThread implements Runnable {    private String name;    private Lock lock;    private Integer flag;    public static int count = 0;    public static int MAX = 9;    public PrintThread(String name, Lock lock, Integer flag) {        this.name = name;        this.lock = lock;        this.flag = flag;    }    @Override    public void run() {        while (true) {            lock.lock();            if (count >= MAX) {                lock.unlock();                return;            }            if (count % 3 == flag) {                System.out.print(name.charAt(count / 3) + " ");                count++;            }            lock.unlock();        }    }}
  • 输出结果。
    image.png
第二种思路
  • 和上面的思路是一样的。

  • 手写代码

public class DemoOne {    public static void main(String[] args) throws InterruptedException {        for (int i = 0; i < 3; i++) {            Thread a = new Thread(new MyThread("abc", i));            a.start();            a.join();            Thread b = new Thread(new MyThread("def", i));            b.start();            b.join();            Thread c = new Thread(new MyThread("ghi", i));            c.start();            c.join();            System.out.println("");        }    }}class MyThread implements Runnable {    private String str;    private int index;    public MyThread(String str, int index) {        this.str = str;        this.index = index;    }    @Override    public void run() {        System.out.print(String.valueOf(str.charAt(index)) + " ");    }}
  • 输出结果。
    image.png

面试

昨天去扫呗面试,面试官问我多线程的实现的二种方式和彼此之间的区别。这个也很简单,百度也烂大街了。

  • 采用extends Thread 方式

    • 优点:编程简单,如果要访问当前线程,无需使用Thread.currentThread()方法,可以直接用this,即可获取当前线程。

    • 缺点:由于继承了Thread,类无法再继承其他的父类。

    • 使用方式:直接new 相应的线程类即可。

  • 采用implements Runnable 方式

    • 优点:没有继承Thread类,所以可以继承其他的父类,在这种形式下,多个线程可以共享同一个对象,所以非常合适多个相同的线程来处理同一份资源的情况下,把cpu代码和数据分开,形成清晰的模型,较好的体现了面向对象的思想。适用场景,比如卖票。

    • 缺点:编程稍微复杂,如果要访问当前线程,必须使用Thread.currentThread()方法。

    • 使用方式:不能直接创建所需类的对象并运行它,而是必须从Thread类的一个实例内部启动它。

    public Thread(Runnable target) {        init(null, target, "Thread-" + nextThreadNum(), 0);    }

尾言

就算失望不能绝望,明天又去面试,美滋滋。

原创粉丝点击