欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

一道有意思的多线程面试题 C# 代码实现

程序员文章站 2022-05-03 11:20:14
如果你对多线程的控制不怎么了解,那么理解了这篇文章的内容也许对你有帮助。鼓励先自己动手实现一遍,做不出来在看代码。 题目一:两个线程交替打印0~100的奇偶数 这道题就是说有两个线程,一个名为偶数线程,一个名为奇数线程,偶数线程只打印偶数,奇数线程只打印奇数,两个线程按顺序交替打印。本文重点不是说的 ......

 

如果你对多线程的控制不怎么了解,那么理解了这篇文章的内容也许对你有帮助。鼓励先自己动手实现一遍,做不出来在看代码。

 

题目一:两个线程交替打印0~100的奇偶数

这道题就是说有两个线程,一个名为偶数线程,一个名为奇数线程,偶数线程只打印偶数,奇数线程只打印奇数,两个线程按顺序交替打印。本文重点不是说的这道题,这道题是下面那道题的简单版本,用来做个过渡。

效果图:

一道有意思的多线程面试题 C# 代码实现

此题核心点就是如何控制多线程的执行顺序,我们知道c#的system.threading命名空间给开发者提供了控制线程相关的对象,线程同步常用对象有:semaphore,manualresetevent,autoresetevent,这里我用autoresetevent来实现,代码如下:

一道有意思的多线程面试题 C# 代码实现
public class threadexample
{
    /// <summary>
    /// 两个线程交替打印0~100的奇偶数
    /// </summary>
    public static void printoddevennumber()
    {
        var work = new theadworktest();
        var thread1 = new thread(work.printoddnumer) { name = "奇数线程" };
        var thread2 = new thread(work.printevennumber) { name = "偶数线程" };
        thread1.start();
        thread2.start();
    }
}

public class theadworktest
{
    private static readonly autoresetevent oddare = new autoresetevent(false);
    private static readonly autoresetevent evenare = new autoresetevent(false);

    public void printoddnumer()
    {
        oddare.waitone();
        for (var i = 0; i < 100; i++)
        {
            if (i % 2 != 1) continue;
            console.writeline($"{thread.currentthread.name}:{i}");
            evenare.set();
            oddare.waitone();
        }
    }

    public void printevennumber()
    {
        for (var i = 0; i < 100; i++)
        {
            if (i % 2 != 0) continue;
            console.writeline($"{thread.currentthread.name}:{i}");
            oddare.set();
            evenare.waitone();
        }
    }
}
view code

我这里是两个线程调用不同的方法实现,可读性会好点,如果只调用一个同样的方法你们会怎么实现呢?

题目二:通过n个线程顺序循环打印0~100

这篇文章主要是说这道题,此题据称是阿里的面试题,具体效果如下:

通过n个线程顺序循环打印从0至100,如给定n=3则输出:
一道有意思的多线程面试题 C# 代码实现

 这个题开始真没想出来,后来无意在github上有人用java做出了答案,看到使用了semaphore去控制,我就用c#代码做了下,代码如下:

一道有意思的多线程面试题 C# 代码实现
public class threadexample
{

    /// <summary>
    /// n个线程顺序循环打印从0至100
    /// </summary>
    /// <param name="n"></param>
    public static void printnumber(int n = 3)
    {
        var work = new theadworktest { semaphores = new semaphore[n] };
        for (var i = 0; i < n; i++)
        {
            work.semaphores[i] = new semaphore(1, 1);
            if (i != n - 1)
                work.semaphores[i].waitone();
        }
        for (var i = 0; i < n; i++)
        {
            new thread(work.printnumber) { name = "线程" + i }.start(i);
        }
    }
}

public class theadworktest
{
    public semaphore[] semaphores { get; set; }
    public static int index;
    public void printnumber(object c)
    {
        var i = convert.toint32(c);
        var presemaphore = i == 0 ? semaphores[semaphores.length - 1] : semaphores[i - 1];
        var cursemaphore = semaphores[i];
        while (true)
        {
            presemaphore.waitone();
            interlocked.increment(ref index);
            if (index > 99)
                return;
            console.writeline($"{thread.currentthread.name}:{index}");
            cursemaphore.release();
        }
    }
}
view code

 

如果现实面试我第一次碰上了这样的题目,估计是答不上来了,那么你们觉得出这样难度面试题的公司月薪给多少k合适?

完整代码:https://github.com/ax0ne/example.leetcode/blob/master/src/example.leetcode/problems/threadexample.cs  欢迎star哟,后面会陆续添加一些有意思的题目代码。

博友们还能有不同的实现方式吗 ? ^_^