如何控制方法的执行时间

时间:2021-02-18 18:15:18
public IList A() 
        { 

            IList aylist = B(); 
        } 


        public IList B() 
        { 
            ArrayList arlist = new ArrayList(); 
            for (int i = 0; i < 100; i++) 
            { 
                arlist.Add(i); 
            } 

            return arlist; 
        } 


A()被其他的调用,因为B()的执行时间比较长,如果执行时间超过10s的时候,我就想在A()中直接返回一个null的值,我考虑用: 

              System.Timers.Timer  aTimer  =  new  System.Timers.Timer(10000);  //实例化Timer类,设置间隔时间为10000毫秒; 
                aTimer.Elapsed+=new  ElapsedEventHandler(OnTimedEvent);  //到达时间的时候执行事件 
                //  Only  raise  the  event  the  first  time  Interval  elapses.  
                aTimer.AutoReset  =  false;  //设置是执行一次(false)还是一直执行(true); 
                aTimer.Enabled  =  true;  //是否执行System.Timers.Timer.Elapsed事件; 
      
大家帮忙看看如何高效的写这段代码啊? 

32 个解决方案

#1




public IList B()
{
    int start = System.Environment.TickCount;  //记住起始时间

    ArrayList arlist = new ArrayList();
    for (int i = 0; i < 100; i++)
    {
        if (System.Environment.TickCount - start > 10 * 1000)  // 如果超时则返回
        {
            return null;
        }
        arlist.Add(i);
    }

    return arlist;

#2


同意
1楼正解

#3


to:gomoku

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,请再帮忙看看


#4


首先不知道你为什么要这么干,世界之大真的是无奇不有啊,嘿嘿
如果你一定要实现可以这样

public IList A() 
        { 

            IList aylist = B(); 
            return aylist;
        } 


        public IList B() 
        { 
int timeStamp = Environment.Tickcount;
            ArrayList arlist = new ArrayList(); 
            for (int i = 0; i < 100; i++) 
            { 
if(Environment.TickCount - timeStamp > 10000)
{
return null;
}
                arlist.Add(i); 
            } 

            return arlist; 
        } 

#5


也可以使用线程
超过时间就把这个线程干掉~~

#6


to:gomoku,tmxk2002 

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,b()中的业务蛮复杂的。请再帮忙看看 


#7



如何来写a,能否写一下a?

引用 5 楼 lovefootball 的回复:
也可以使用线程 
超过时间就把这个线程干掉~~

#8


引用 6 楼 echoxue 的回复:
to:gomoku,tmxk2002 

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,b()中的业务蛮复杂的。请再帮忙看看 


你可以做完之后判断呀,具体就是用结速时间-开始的

int start = System.Environment.TickCount;  //记住起始时间

   这里进行你的业务判断 


if (System.Environment.TickCount - start > 10 * 1000)  // 如果超时则返回
   {
      return null;
  }
      
  }


#9


这里进行你的业务判断 
这里可能就会超过10s啊,如果这样程序不是还在执行吗?这样就会超时 ,我的意思就是这个b()方法如果执行的时间超过10s,就要赶快返回null。
到了

if (System.Environment.TickCount - start > 10 * 1000)  // 如果超时则返回
   {
      return null;
  }
      
  }

可能已经执行时间超时了啊



引用 8 楼 zhnzzy 的回复:
引用 6 楼 echoxue 的回复:
to:gomoku,tmxk2002 

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,b()中的业务蛮复杂的。请再帮忙看看 
 

你可以做完之后判断呀,具体就是用结速时间-开始的 

C# code
int start = System.Environment.TickCount;  //记住起始时间

   这里进行你的业务判断 


if (System.Environment.Ti…

#10


public class Test
{
public IList A() 
        { 

            IList aylist = B(); 
            return aylist; 
        } 

AutoResetEvent[] _events = null;
        public IList B() 
        { 
Thread[] _threads = new Thread[10];
_events = new AutoResetEvent[10];
for(int i = 0; i < threads.Length;i ++)
{
_threads[i] = new Thread(RunInTrehad);
_events[i] = new AutoResetEvent(false);
_thread[i].Start(i);
}
AutoResetEvent.WaitAll(_events);
return new List();
        } 

public void RunInThread(object data)
{
int index = Convert.ToInter32(data);
int timeStamp = Environment.Tickcount; 
            ArrayList arlist = new ArrayList(); 
            for (int i = 0; i < 100; i++) 
            { 
if(Environment.TickCount - timeStamp > 10000) //保证每个线程运行的时间不会超过10s,那么整个运行的时间就不会超过10s

_events[i].Set(); 
return;

                arlist.Add(i); 
            } 

    _events[i].Set();        

}
}

大致意思就是主线程阻塞住等待所有子线程返回,每个子线程的执行时间不会超过10s,超过就立即让线程自动结束,那么整体就不会超过10s了,不要去abort线程,这样会导致资源被耗尽的。

#11


谢谢大家,其实我想在A()中能否注册一个监听器

A()
{
System.Timers.Timer  aTimer  =  new  System.Timers.Timer(10000);  //实例化Timer类,设置间隔时间为10000毫秒; 
                aTimer.Elapsed+=new  ElapsedEventHandler(OnTimedEvent);  //到达时间的时候执行事件 
                //  Only  raise  the  event  the  first  time  Interval  elapses.  
                aTimer.AutoReset  =  false;  //设置是执行一次(false)还是一直执行(true); 
                aTimer.Enabled  =  true;  //是否执行System.Timers.Timer.Elapsed事件; 

B();

}


   private static void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            
        }
这样B()在继续执行,但是当到了10000毫秒的时候,会调用OnTimedEvent,但是B()还是在执行中,我仅仅提供一个思路。我说过B()业务很复杂,牵涉B()又调用了其他的方法,框架已经好了,我要加上去这个超过时间的限制就返回,不知道如何处理了?

谢谢!

#12


你就是说如果到时间了就去把所有的线程abort掉?如果你不需要去终止线程,干嘛要等10s呢?线程本来就是为了异步操作的,如果你要abort,你的程序在运行一段时间后就有可能会因为资源耗尽而崩掉,因为abort线程,线程所占的资源很有可能不会全部释放。
我刚刚写的方案应该比较理想的,让线程自己判断时间主动退出去,而且效率也高,因为线程是阻塞住的,不占cpu。

#13


to:tmxk2002

很感谢,试试按照你的思路改一下。又问题再请教!

#14




to:all

可能我表达的不是很清楚,其实很简单的实现了
利用thread的join方法,join有3个方法
1,无限期的等待线程zhixing
2,join(int timeout时间)
3,join(timespan)


public class Test 

public IList A() 
        { 

         Thread thread = new thread(new ThreadStrsat(B)) :
thread.start();
therad.join(20000);          

private B()
{
.......
}





#15


大家看看是否不妥,讨论一下,谢谢!

#16


首先我记得好像join是不推荐用的,会容易导致死锁什么的
然后这样你这样过了20000秒怎么办?还是要去杀线程啊,因为可能前面的线程仍然没有做完啊

原则是一定要让其他线程主动退出,
不知道你那些线程是不是不停在做循环,如果是这样倒有个折中的办法,就是循环的开关变量是你这个类的一个私有bool变量,当主线程等待20000秒后,把这个变量变成true,就可以让所有子线程主动退出了。

#17


to:tmxk2002

1,是的,我也想到了你所说的其他的线程没有完成的问题。
2,其他的线程是在做循环,一时想不出好的解决方法,如果像你所说的,加上这个bool的变量,那么代码要改的很多了。我是线程中嵌套线程。还有其他的思路吗?

#18


to:tmxk2002 

我说说的代码流程
1,其实我用的是webservice的机制。我在webservice调用了一个项目的(libary)的dll。
2,在这个项目的dll,是大的3个线程,然后每个线程又分成5个小的子线程。
3,我在webservice的这端就是写了一个线程去执行这个dll,就是3个大的线程。

基本上是这样,因为客户反映有的时候timeout,那么我就想自己控制一个时间20s,如果在20s还是没有查询到结果,那么就主动的返回客户端说目前系统busy(笨招)。

您的想法呢?

#19


to:tmxk2002 

我在想是否我可以利用后台线程机制啊?
《应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束 》

因为我用户调用我的webservice,那么我开的线程都是基于webservice的。我把所有的线程都置为后台线程,在webservice断开连接的时候,是不是就是所有的线程都中止了呢?

#20


不会的,你请求结束,并不代表webserverice应用程序域退出。这样会很危险的

从你描述的情况来,整个系统设计非常糟糕,一个请求会开到15个线程,而且好像线程执行的时间还挺长的,20s已经是相当长了。这20s内会有多少个请求??你算下最差的情况下(每个线程消耗20s)每秒钟100个请求(应该不多),100*20*15=30000,呵呵,一个进程在一个请求周期内可能同时开到3w个线程,不慢才怪。一个进程同时开到20个线程基本上是最优的,开到1000个线程就已经会导致系统调配线程很费资源了。即使这种情况一天只出现几次也会导致你系统进入一个恶性循环当中,甚至于崩掉。

我觉得要解决这个问题,还是从优化你线程执行上去做,否则都是治标不治本。

#21


引用 16 楼 tmxk2002 的回复:
首先我记得好像join是不推荐用的,会容易导致死锁什么的 
然后这样你这样过了20000秒怎么办?还是要去杀线程啊,因为可能前面的线程仍然没有做完啊 

原则是一定要让其他线程主动退出, 
不知道你那些线程是不是不停在做循环,如果是这样倒有个折中的办法,就是循环的开关变量是你这个类的一个私有bool变量,当主线程等待20000秒后,把这个变量变成true,就可以让所有子线程主动退出了。

不是Join不推荐,是Abort不推荐。
Join就在阻塞等待线程推出,是合理的用法。

#22


不是Join不推荐,是Abort不推荐。 
Join就在阻塞等待线程推出,是合理的用法。
--------------
我所说的不推荐用,不是说它本身存在问题,而是使用者在使用它时很容易导致相关联的thread互相join导致死锁。

#23


to:tmxk2002 
你说的很有道理,是设计上有问题,根据log的记录我已经发现发生资源不够用的问题。

目前没有考虑到好的设计框架,是系统在不断的search数据库然后再到内存交互匹配,时间是比较长的。
有如下几点疑问:

1,那么说就是我join完毕,其实还是又子线程在运行了?
2,webserverice应用程序域是一个进程(A),那么当一个用户1请求的时候,是在这个进程(A)内,那么其他用户(2-100)请求的时候,是不是共享这个webserverice应用程序域,即这个进程(A)呢?
3,一个进程同时开到20个线程基本上是最优的,这个计算依据是根据什么啊?考虑到CPU以及内存的情况了吗?

谢谢!


#24


up

#25


1,那么说就是我join完毕,其实还是又子线程在运行了? 
是的,因为你是超时来实现的,超时了当前线程就不会理会子线程了,子线程当然还在运行

2,webserverice应用程序域是一个进程(A),那么当一个用户1请求的时候,是在这个进程(A)内,那么其他用户(2-100)请求的时候,是不是共享这个webserverice应用程序域,即这个进程(A)呢? 
当然,java好像是每个请求会去开一个进程,但netframework只会去开线程,所以不会自动关掉。

3,一个进程同时开到20个线程基本上是最优的,这个计算依据是根据什么啊?考虑到CPU以及内存的情况了吗? 
这个是微软内部的windows专家推荐的,你自己也可以做测试,基本上是每cpu一个进程25个线程,因为本身进程启动后会占掉5-6个线程,所以15-20个线程是最优的。如果你的机器是多cpu的,那么可以开到n cpu * 20个线程的样子。


不知道你的系统到底是怎样的查询,需要同时查多个数据库或者多个表?数据量有多大呢?为什么要采用多线程的方式去查,通常一个查询就够了。提高查询速度,首先考虑的是优化数据库,而不是通过你现在的这种方式,因为你现在的方式是牺牲其他资源来获取查询的并发,很有可能得不偿失。

#26


to:tmxk2002 

我简单说一下系统的设计:
1,根据合同的类型去分别查询3种类型的合同A,B,C
即:开3和线程去执行数据库查询得到A,B,C类型的合同
2,根据得到的合同类型A,B,C再去开5个小的线程去执行所查询到的合同,根据每份合同的ID,去做相关的匹配,还是会查询数据库,然后再在内存中交互匹配得到search的结果。然后加到IList中。

3,A类型的合同比较少,一般是在10S结束,B类型的合同较多,一般14s结束,C类型的合同最多,执行的时间有时会大于20s。所以我就想在不超过20s的时候返回查询结果。

粗糙的设计,见笑了,根据我的描述,能否给点建议?占用你的时间,谢谢!





#27


to:tmxk2002 

目前是这样用的

thread A = new Thread(new ThreadStart(AA.ThreadSearch));
thread B = new Thread(new ThreadStart(BB.ThreadSearch));
thread C = new Thread(new ThreadStart(CC.ThreadSearch));
A.start();
B.start();
C.start();

C.Join();
B.Join();
A.Join();

因为C阻塞主线程,那么自己感觉这种方式不是很好?不知道是否您有好的建议?
以前看到一个例子:
private static void joinAllThread(object obj)
{
    Thread[] threads = obj as Thread[];
    foreach (Thread t in threads)
        t.Join();
    Console.WriteLine("所有的线程结束");
}

 Thread joinThread = new Thread(joinAllThread);
     joinThread.Start(new Thread[] { C, B, A});

但是感觉这种方式跟我写的不是一样吗?除非主线程运行的时候有一个线程D,这样就不会阻塞线程D了。

#28


这种做法肯定不行的,join并不代表不占资源啊


不知道你最大的数据表有多少数据?有几千万吗?是否对数据库做过优化,怎么一个查询少则要10来秒?这种查询肯定有问题,先从数据库优化开始吧,如果数据量实在太大,可以自己再做索引表,至少先找出这次查询涉及到的所有合同号,然后根据合同号来分配线程,保证每个线程查询的速度尽可能短,能及时释放资源。至于合并合同的操作,为什么不放到调用webservice的一端去操作呢?你调用方是什么?

#29


to:tmxk2002 

http://topic.csdn.net/u/20081023/14/a7f77f32-c28e-4466-b4f0-c142e672a66a.html

最大的数据表的数据是30万条,涉及的表是80多张。

其实不是一次查询就10s的,是根据得到的合同(一般是60份,如果用户search all的条件)来匹配查询。一份合同的处理时间是接近3000ms,其实我是开线程去处理合同的。就是开几个线程去同时处理60份合同,


调用代码:
if ( contracts != null && contracts.Count >0 )
{
int ThreadNumber = Environments.NetThreadNumber; 
Thread[] MutiThread = new Thread[ThreadNumber];
NetThreadSearch mutiThread  = new NetThreadSearch(
contracts,this,searchParams,airways,
this.searchContext.depAirportGroupList ,
this.searchContext.destAirportGroupList ,
this.searchContext.depZoneList,
this.searchContext.destZoneList);

for (int i = 0; i < ThreadNumber; i++) 

MutiThread[i] = new Thread(new ThreadStart(mutiThread.MutiThreadSearch)); 
MutiThread[i].Name = "NET Thread " + i.ToString(); 
MutiThread[i].Priority = ThreadPriority.Highest;
MutiThread[i].Start(); 


for(int i = 0; i < ThreadNumber; i++)
{
MutiThread[i].Join();
}

srl = mutiThread.ROUTING;
}

处理合同的类:


public void MutiThreadSearch()
{
AbstractSearchStrategy.DbConnection = new SqlConnection(SearchFactory.DBConnection);
AbstractSearchStrategy.DbConnection.Open();

try
{
while( true )
{
if ( contracts.Count == 0 )
{
break;
}

Contract contract = null;
mut.WaitOne();
if ( contracts.Count > 0 )
{
contract =  (Contract)contracts.GetRange(0,1)[0];
contracts.RemoveAt(0);

mut.ReleaseMutex();

}
else
{
mut.ReleaseMutex();
break;
}

if(contract.FareType.Trim() != Environments.BULKFARETYPE && contract.FareType.Trim() != Environments.COMMISSIONFARETYPE)
continue;

if(airways.Trim().ToUpper() != "ALL" && airways.IndexOf(contract.Airway.AirlineCode.ToUpper()) == -1)
continue;

// one NET contract INFO
ArrayList temp = (ArrayList)searchNet.GetAvailableRouting(
contract,
searchParams.Departure,
searchParams.Destination,
searchParams.ReturnFrom,
searchParams.ReturnTo,
searchParams.DepartureDate,
searchParams.ReturnDate,
searchParams.TourType,
null,
this.depAirportGroupList ,
this.destAirportGroupList ,
this.depZoneList,
this.destZoneList
);

mut.WaitOne();

if(temp != null && temp.Count > 0)
{
ROUTING.AddRange(temp);     
}

mut.ReleaseMutex();
}
}
catch(Exception Ex)
{
log.Error(Ex.Message,Ex); 
if (mut.WaitOne())
mut.ReleaseMutex();
}

AbstractSearchStrategy.DbConnection.Close();
}
#endregion

基本是是这样,在GetAvailableRouting这个方法中就是跟数据库的交互匹配查询的,自己知道在线程中访问数据库是不妥。但是目前考虑不到更好的方法

根据代码给点建议!

谢谢

#30


to:tmxk2002 

1,然后根据合同号来分配线程,保证每个线程查询的速度尽可能短,能及时释放资源。

如何根据合同的多少来开线程,这样不是线程更多了吗,就是违背你说的一个进程最好25个线程的原则了吗?

2,至于合并合同的操作,为什么不放到调用webservice的一端去操作呢?你调用方是什么?

我开始说过是在参照的一个library的dll的方式,这样改动比较大了,我的调用方是net的,目前没有考虑到java的。

#31


25个线程是并发的数量,如果你线程是短线程就没有关系的,要知道你的每个请求,iis也是会去开一个线程的,只是因为线程中的操作非常短,所以它才不会出现资源不足的情况,如果你一个请求处理的时间很长,即使就单独的webservice调用,也会出现资源不足的情况,原理是一样的。一般一个线程执行时间最好不要超过500ms,越短越好。

如果你的数据查询的动作,就是合并数据的动作,不是在数据库里做的而是在程序里做的,还是建议你放到客户端去做,这样服务器只做数据的查询,然后你可以把损耗的资源(线程占用的资源)分摊到客户端上,而不是服务器上,毕竟服务器的数量有限,而客户端可以无限。

否则的话我认为没有其他更好的解决办法了。

#32


to:tmxk2002 

刚刚来公司,谢谢回复,这个放到客户端是不可能的,因为我们是为客户提供数据的。这个合并数据的动作只能在我这边做,而且我还不能限制这个search all的选项,如果单独的选择search 合同,那么速度还是比较快的,所以我再想想其他的优化巴。

谢谢你的帮忙了

#1




public IList B()
{
    int start = System.Environment.TickCount;  //记住起始时间

    ArrayList arlist = new ArrayList();
    for (int i = 0; i < 100; i++)
    {
        if (System.Environment.TickCount - start > 10 * 1000)  // 如果超时则返回
        {
            return null;
        }
        arlist.Add(i);
    }

    return arlist;

#2


同意
1楼正解

#3


to:gomoku

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,请再帮忙看看


#4


首先不知道你为什么要这么干,世界之大真的是无奇不有啊,嘿嘿
如果你一定要实现可以这样

public IList A() 
        { 

            IList aylist = B(); 
            return aylist;
        } 


        public IList B() 
        { 
int timeStamp = Environment.Tickcount;
            ArrayList arlist = new ArrayList(); 
            for (int i = 0; i < 100; i++) 
            { 
if(Environment.TickCount - timeStamp > 10000)
{
return null;
}
                arlist.Add(i); 
            } 

            return arlist; 
        } 

#5


也可以使用线程
超过时间就把这个线程干掉~~

#6


to:gomoku,tmxk2002 

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,b()中的业务蛮复杂的。请再帮忙看看 


#7



如何来写a,能否写一下a?

引用 5 楼 lovefootball 的回复:
也可以使用线程 
超过时间就把这个线程干掉~~

#8


引用 6 楼 echoxue 的回复:
to:gomoku,tmxk2002 

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,b()中的业务蛮复杂的。请再帮忙看看 


你可以做完之后判断呀,具体就是用结速时间-开始的

int start = System.Environment.TickCount;  //记住起始时间

   这里进行你的业务判断 


if (System.Environment.TickCount - start > 10 * 1000)  // 如果超时则返回
   {
      return null;
  }
      
  }


#9


这里进行你的业务判断 
这里可能就会超过10s啊,如果这样程序不是还在执行吗?这样就会超时 ,我的意思就是这个b()方法如果执行的时间超过10s,就要赶快返回null。
到了

if (System.Environment.TickCount - start > 10 * 1000)  // 如果超时则返回
   {
      return null;
  }
      
  }

可能已经执行时间超时了啊



引用 8 楼 zhnzzy 的回复:
引用 6 楼 echoxue 的回复:
to:gomoku,tmxk2002 

呵呵,这个B()中又很多的业务逻辑啊,在B()中有多线程的,多线程中再调用其他的方法。我不可能这样判断,我仅仅是举了arrlist的例子,b()中的业务蛮复杂的。请再帮忙看看 
 

你可以做完之后判断呀,具体就是用结速时间-开始的 

C# code
int start = System.Environment.TickCount;  //记住起始时间

   这里进行你的业务判断 


if (System.Environment.Ti…

#10


public class Test
{
public IList A() 
        { 

            IList aylist = B(); 
            return aylist; 
        } 

AutoResetEvent[] _events = null;
        public IList B() 
        { 
Thread[] _threads = new Thread[10];
_events = new AutoResetEvent[10];
for(int i = 0; i < threads.Length;i ++)
{
_threads[i] = new Thread(RunInTrehad);
_events[i] = new AutoResetEvent(false);
_thread[i].Start(i);
}
AutoResetEvent.WaitAll(_events);
return new List();
        } 

public void RunInThread(object data)
{
int index = Convert.ToInter32(data);
int timeStamp = Environment.Tickcount; 
            ArrayList arlist = new ArrayList(); 
            for (int i = 0; i < 100; i++) 
            { 
if(Environment.TickCount - timeStamp > 10000) //保证每个线程运行的时间不会超过10s,那么整个运行的时间就不会超过10s

_events[i].Set(); 
return;

                arlist.Add(i); 
            } 

    _events[i].Set();        

}
}

大致意思就是主线程阻塞住等待所有子线程返回,每个子线程的执行时间不会超过10s,超过就立即让线程自动结束,那么整体就不会超过10s了,不要去abort线程,这样会导致资源被耗尽的。

#11


谢谢大家,其实我想在A()中能否注册一个监听器

A()
{
System.Timers.Timer  aTimer  =  new  System.Timers.Timer(10000);  //实例化Timer类,设置间隔时间为10000毫秒; 
                aTimer.Elapsed+=new  ElapsedEventHandler(OnTimedEvent);  //到达时间的时候执行事件 
                //  Only  raise  the  event  the  first  time  Interval  elapses.  
                aTimer.AutoReset  =  false;  //设置是执行一次(false)还是一直执行(true); 
                aTimer.Enabled  =  true;  //是否执行System.Timers.Timer.Elapsed事件; 

B();

}


   private static void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            
        }
这样B()在继续执行,但是当到了10000毫秒的时候,会调用OnTimedEvent,但是B()还是在执行中,我仅仅提供一个思路。我说过B()业务很复杂,牵涉B()又调用了其他的方法,框架已经好了,我要加上去这个超过时间的限制就返回,不知道如何处理了?

谢谢!

#12


你就是说如果到时间了就去把所有的线程abort掉?如果你不需要去终止线程,干嘛要等10s呢?线程本来就是为了异步操作的,如果你要abort,你的程序在运行一段时间后就有可能会因为资源耗尽而崩掉,因为abort线程,线程所占的资源很有可能不会全部释放。
我刚刚写的方案应该比较理想的,让线程自己判断时间主动退出去,而且效率也高,因为线程是阻塞住的,不占cpu。

#13


to:tmxk2002

很感谢,试试按照你的思路改一下。又问题再请教!

#14




to:all

可能我表达的不是很清楚,其实很简单的实现了
利用thread的join方法,join有3个方法
1,无限期的等待线程zhixing
2,join(int timeout时间)
3,join(timespan)


public class Test 

public IList A() 
        { 

         Thread thread = new thread(new ThreadStrsat(B)) :
thread.start();
therad.join(20000);          

private B()
{
.......
}





#15


大家看看是否不妥,讨论一下,谢谢!

#16


首先我记得好像join是不推荐用的,会容易导致死锁什么的
然后这样你这样过了20000秒怎么办?还是要去杀线程啊,因为可能前面的线程仍然没有做完啊

原则是一定要让其他线程主动退出,
不知道你那些线程是不是不停在做循环,如果是这样倒有个折中的办法,就是循环的开关变量是你这个类的一个私有bool变量,当主线程等待20000秒后,把这个变量变成true,就可以让所有子线程主动退出了。

#17


to:tmxk2002

1,是的,我也想到了你所说的其他的线程没有完成的问题。
2,其他的线程是在做循环,一时想不出好的解决方法,如果像你所说的,加上这个bool的变量,那么代码要改的很多了。我是线程中嵌套线程。还有其他的思路吗?

#18


to:tmxk2002 

我说说的代码流程
1,其实我用的是webservice的机制。我在webservice调用了一个项目的(libary)的dll。
2,在这个项目的dll,是大的3个线程,然后每个线程又分成5个小的子线程。
3,我在webservice的这端就是写了一个线程去执行这个dll,就是3个大的线程。

基本上是这样,因为客户反映有的时候timeout,那么我就想自己控制一个时间20s,如果在20s还是没有查询到结果,那么就主动的返回客户端说目前系统busy(笨招)。

您的想法呢?

#19


to:tmxk2002 

我在想是否我可以利用后台线程机制啊?
《应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束 》

因为我用户调用我的webservice,那么我开的线程都是基于webservice的。我把所有的线程都置为后台线程,在webservice断开连接的时候,是不是就是所有的线程都中止了呢?

#20


不会的,你请求结束,并不代表webserverice应用程序域退出。这样会很危险的

从你描述的情况来,整个系统设计非常糟糕,一个请求会开到15个线程,而且好像线程执行的时间还挺长的,20s已经是相当长了。这20s内会有多少个请求??你算下最差的情况下(每个线程消耗20s)每秒钟100个请求(应该不多),100*20*15=30000,呵呵,一个进程在一个请求周期内可能同时开到3w个线程,不慢才怪。一个进程同时开到20个线程基本上是最优的,开到1000个线程就已经会导致系统调配线程很费资源了。即使这种情况一天只出现几次也会导致你系统进入一个恶性循环当中,甚至于崩掉。

我觉得要解决这个问题,还是从优化你线程执行上去做,否则都是治标不治本。

#21


引用 16 楼 tmxk2002 的回复:
首先我记得好像join是不推荐用的,会容易导致死锁什么的 
然后这样你这样过了20000秒怎么办?还是要去杀线程啊,因为可能前面的线程仍然没有做完啊 

原则是一定要让其他线程主动退出, 
不知道你那些线程是不是不停在做循环,如果是这样倒有个折中的办法,就是循环的开关变量是你这个类的一个私有bool变量,当主线程等待20000秒后,把这个变量变成true,就可以让所有子线程主动退出了。

不是Join不推荐,是Abort不推荐。
Join就在阻塞等待线程推出,是合理的用法。

#22


不是Join不推荐,是Abort不推荐。 
Join就在阻塞等待线程推出,是合理的用法。
--------------
我所说的不推荐用,不是说它本身存在问题,而是使用者在使用它时很容易导致相关联的thread互相join导致死锁。

#23


to:tmxk2002 
你说的很有道理,是设计上有问题,根据log的记录我已经发现发生资源不够用的问题。

目前没有考虑到好的设计框架,是系统在不断的search数据库然后再到内存交互匹配,时间是比较长的。
有如下几点疑问:

1,那么说就是我join完毕,其实还是又子线程在运行了?
2,webserverice应用程序域是一个进程(A),那么当一个用户1请求的时候,是在这个进程(A)内,那么其他用户(2-100)请求的时候,是不是共享这个webserverice应用程序域,即这个进程(A)呢?
3,一个进程同时开到20个线程基本上是最优的,这个计算依据是根据什么啊?考虑到CPU以及内存的情况了吗?

谢谢!


#24


up

#25


1,那么说就是我join完毕,其实还是又子线程在运行了? 
是的,因为你是超时来实现的,超时了当前线程就不会理会子线程了,子线程当然还在运行

2,webserverice应用程序域是一个进程(A),那么当一个用户1请求的时候,是在这个进程(A)内,那么其他用户(2-100)请求的时候,是不是共享这个webserverice应用程序域,即这个进程(A)呢? 
当然,java好像是每个请求会去开一个进程,但netframework只会去开线程,所以不会自动关掉。

3,一个进程同时开到20个线程基本上是最优的,这个计算依据是根据什么啊?考虑到CPU以及内存的情况了吗? 
这个是微软内部的windows专家推荐的,你自己也可以做测试,基本上是每cpu一个进程25个线程,因为本身进程启动后会占掉5-6个线程,所以15-20个线程是最优的。如果你的机器是多cpu的,那么可以开到n cpu * 20个线程的样子。


不知道你的系统到底是怎样的查询,需要同时查多个数据库或者多个表?数据量有多大呢?为什么要采用多线程的方式去查,通常一个查询就够了。提高查询速度,首先考虑的是优化数据库,而不是通过你现在的这种方式,因为你现在的方式是牺牲其他资源来获取查询的并发,很有可能得不偿失。

#26


to:tmxk2002 

我简单说一下系统的设计:
1,根据合同的类型去分别查询3种类型的合同A,B,C
即:开3和线程去执行数据库查询得到A,B,C类型的合同
2,根据得到的合同类型A,B,C再去开5个小的线程去执行所查询到的合同,根据每份合同的ID,去做相关的匹配,还是会查询数据库,然后再在内存中交互匹配得到search的结果。然后加到IList中。

3,A类型的合同比较少,一般是在10S结束,B类型的合同较多,一般14s结束,C类型的合同最多,执行的时间有时会大于20s。所以我就想在不超过20s的时候返回查询结果。

粗糙的设计,见笑了,根据我的描述,能否给点建议?占用你的时间,谢谢!





#27


to:tmxk2002 

目前是这样用的

thread A = new Thread(new ThreadStart(AA.ThreadSearch));
thread B = new Thread(new ThreadStart(BB.ThreadSearch));
thread C = new Thread(new ThreadStart(CC.ThreadSearch));
A.start();
B.start();
C.start();

C.Join();
B.Join();
A.Join();

因为C阻塞主线程,那么自己感觉这种方式不是很好?不知道是否您有好的建议?
以前看到一个例子:
private static void joinAllThread(object obj)
{
    Thread[] threads = obj as Thread[];
    foreach (Thread t in threads)
        t.Join();
    Console.WriteLine("所有的线程结束");
}

 Thread joinThread = new Thread(joinAllThread);
     joinThread.Start(new Thread[] { C, B, A});

但是感觉这种方式跟我写的不是一样吗?除非主线程运行的时候有一个线程D,这样就不会阻塞线程D了。

#28


这种做法肯定不行的,join并不代表不占资源啊


不知道你最大的数据表有多少数据?有几千万吗?是否对数据库做过优化,怎么一个查询少则要10来秒?这种查询肯定有问题,先从数据库优化开始吧,如果数据量实在太大,可以自己再做索引表,至少先找出这次查询涉及到的所有合同号,然后根据合同号来分配线程,保证每个线程查询的速度尽可能短,能及时释放资源。至于合并合同的操作,为什么不放到调用webservice的一端去操作呢?你调用方是什么?

#29


to:tmxk2002 

http://topic.csdn.net/u/20081023/14/a7f77f32-c28e-4466-b4f0-c142e672a66a.html

最大的数据表的数据是30万条,涉及的表是80多张。

其实不是一次查询就10s的,是根据得到的合同(一般是60份,如果用户search all的条件)来匹配查询。一份合同的处理时间是接近3000ms,其实我是开线程去处理合同的。就是开几个线程去同时处理60份合同,


调用代码:
if ( contracts != null && contracts.Count >0 )
{
int ThreadNumber = Environments.NetThreadNumber; 
Thread[] MutiThread = new Thread[ThreadNumber];
NetThreadSearch mutiThread  = new NetThreadSearch(
contracts,this,searchParams,airways,
this.searchContext.depAirportGroupList ,
this.searchContext.destAirportGroupList ,
this.searchContext.depZoneList,
this.searchContext.destZoneList);

for (int i = 0; i < ThreadNumber; i++) 

MutiThread[i] = new Thread(new ThreadStart(mutiThread.MutiThreadSearch)); 
MutiThread[i].Name = "NET Thread " + i.ToString(); 
MutiThread[i].Priority = ThreadPriority.Highest;
MutiThread[i].Start(); 


for(int i = 0; i < ThreadNumber; i++)
{
MutiThread[i].Join();
}

srl = mutiThread.ROUTING;
}

处理合同的类:


public void MutiThreadSearch()
{
AbstractSearchStrategy.DbConnection = new SqlConnection(SearchFactory.DBConnection);
AbstractSearchStrategy.DbConnection.Open();

try
{
while( true )
{
if ( contracts.Count == 0 )
{
break;
}

Contract contract = null;
mut.WaitOne();
if ( contracts.Count > 0 )
{
contract =  (Contract)contracts.GetRange(0,1)[0];
contracts.RemoveAt(0);

mut.ReleaseMutex();

}
else
{
mut.ReleaseMutex();
break;
}

if(contract.FareType.Trim() != Environments.BULKFARETYPE && contract.FareType.Trim() != Environments.COMMISSIONFARETYPE)
continue;

if(airways.Trim().ToUpper() != "ALL" && airways.IndexOf(contract.Airway.AirlineCode.ToUpper()) == -1)
continue;

// one NET contract INFO
ArrayList temp = (ArrayList)searchNet.GetAvailableRouting(
contract,
searchParams.Departure,
searchParams.Destination,
searchParams.ReturnFrom,
searchParams.ReturnTo,
searchParams.DepartureDate,
searchParams.ReturnDate,
searchParams.TourType,
null,
this.depAirportGroupList ,
this.destAirportGroupList ,
this.depZoneList,
this.destZoneList
);

mut.WaitOne();

if(temp != null && temp.Count > 0)
{
ROUTING.AddRange(temp);     
}

mut.ReleaseMutex();
}
}
catch(Exception Ex)
{
log.Error(Ex.Message,Ex); 
if (mut.WaitOne())
mut.ReleaseMutex();
}

AbstractSearchStrategy.DbConnection.Close();
}
#endregion

基本是是这样,在GetAvailableRouting这个方法中就是跟数据库的交互匹配查询的,自己知道在线程中访问数据库是不妥。但是目前考虑不到更好的方法

根据代码给点建议!

谢谢

#30


to:tmxk2002 

1,然后根据合同号来分配线程,保证每个线程查询的速度尽可能短,能及时释放资源。

如何根据合同的多少来开线程,这样不是线程更多了吗,就是违背你说的一个进程最好25个线程的原则了吗?

2,至于合并合同的操作,为什么不放到调用webservice的一端去操作呢?你调用方是什么?

我开始说过是在参照的一个library的dll的方式,这样改动比较大了,我的调用方是net的,目前没有考虑到java的。

#31


25个线程是并发的数量,如果你线程是短线程就没有关系的,要知道你的每个请求,iis也是会去开一个线程的,只是因为线程中的操作非常短,所以它才不会出现资源不足的情况,如果你一个请求处理的时间很长,即使就单独的webservice调用,也会出现资源不足的情况,原理是一样的。一般一个线程执行时间最好不要超过500ms,越短越好。

如果你的数据查询的动作,就是合并数据的动作,不是在数据库里做的而是在程序里做的,还是建议你放到客户端去做,这样服务器只做数据的查询,然后你可以把损耗的资源(线程占用的资源)分摊到客户端上,而不是服务器上,毕竟服务器的数量有限,而客户端可以无限。

否则的话我认为没有其他更好的解决办法了。

#32


to:tmxk2002 

刚刚来公司,谢谢回复,这个放到客户端是不可能的,因为我们是为客户提供数据的。这个合并数据的动作只能在我这边做,而且我还不能限制这个search all的选项,如果单独的选择search 合同,那么速度还是比较快的,所以我再想想其他的优化巴。

谢谢你的帮忙了