Skip to main content
 首页 » 编程设计

C# 自制线程池3续

2022年07月19日145thcjp

晚上睡觉前想到一些问题,发现有几种情形没有进行测试,遂记录下来进行了今天进行了测试

1.在给线程池派发任务执行完成后,间隔一段时间,再给线程池添加任务看是否正常,根据间隔的时间的长短这里可以分为两种情形,一是复用空闲的线程,另一种是创建线程。

创建线程的情况又分为两种,一种是由于间隔时间过长,系统自动将线程结束了,另一种是线程池设定了最大执行任务时间,虽然间隔的时间不长,但是任务的线程是强制销毁的还是要创建新线程来执行下面的任务。

在测试的时间我发我现一个鬼异的现象,我先把我的测试代码例出来

using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading;
using  ThreadPool2;

namespace  ThreadPoolTest.MyThreadPool2Test
{
    
class Class3
    
{
        
static void Main(string[] args)
        
{
            MyThreadPool2 pool
=new MyThreadPool2(1,true,10*1000);
            
object state=new object();
            pool.QueueUserWorkItem(call1,state,succ,err);
            Thread.Sleep(
80*1000);
            pool.QueueUserWorkItem(call1, state, succ, err);
            Thread.Sleep(
50* 1000);
            pool.QueueUserWorkItem(call1, state, succ, err);

            Console.ReadLine();
        }


        
private static void err(object state)
        
{
            Console.WriteLine(
"err");
        }


        
private static void succ(object state, object result)
        
{
            Console.WriteLine(
"succ");
        }


        
private static object call1(object state)
        
{
            
while(true)
            
{
                Console.WriteLine(
"call1");
                Thread.Sleep(
2000);
            }

        }

    }

}

这里正常的情况应该是这样,执行单项任务最长为10s,两次向线程池提交任务都会创建新的线程来执行,因为10s,第一项加入线程池的任务是完不成的需要强行销毁线程。所以第二项不能复用第一项的任务。

这里有趣的现象是,我发现第一项任务的执行时间将近20s,而后面第二次加入的任务执行都是标准的10s这个是为什么?

明明设定了最大执行10s,仅是第一次执行任务不是,为什么?

最后我发现的原因是这样,由于实例化线程池时就开始轮询检测是否有超时任务,而此时还没有向线程池中添加任务,当向线程池中添加任务后,轮询到达第一次10s检测时间,而此时任务的执行时间还未到10s,等到第二次轮询到达时才认为任务超时了,所以第一次加入的任务它比后面的任务执行的长间较长,我们可以通过下面的代码来显现我的观点的正确性

using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading;
using  ThreadPool2;

namespace  ThreadPoolTest.MyThreadPool2Test
{
    
class Class3
    
{
        
static void Main(string[] args)
        
{
            MyThreadPool2 pool
=new MyThreadPool2(1,true,10*1000);
            Thread.Sleep(5000);

            
object state=new object();
            pool.QueueUserWorkItem(call1,state,succ,err);
            Thread.Sleep(
80*1000);
            pool.QueueUserWorkItem(call1, state, succ, err);
            Thread.Sleep(
50* 1000);
            pool.QueueUserWorkItem(call1, state, succ, err);

            Console.ReadLine();
        }


        
private static void err(object state)
        
{
            Console.WriteLine(
"err");
        }


        
private static void succ(object state, object result)
        
{
            Console.WriteLine(
"succ");
        }


        
private static object call1(object state)
        
{
            
while(true)
            
{
                Console.WriteLine(
"call1");
                Thread.Sleep(
2000);
            }

        }

    }

}

上图是原来的结果

下图是加了Thread.Sleep(5000)的结果,可以看出,执行的时间少了5s钟,由此可以证明确实是因为记时和任务执行的时间不一致性所引起的。

我本来想改进一下,可后来想了想还是算了,这个问题不大,因为在实际项目中,我们只是要将死亡的任务销毁,我们不需要太过精确,只能执行10分钟,一分也不能多或不能少,差不多就行。

不过等我静下心来,我可以认真的去改进它


本文参考链接:https://www.cnblogs.com/lexus/archive/2008/08/13/1266847.html