zoukankan      html  css  js  c++  java
  • Perl语言的多线程(二)

    很多时候使用perl多线程可以达到很不错的效果,可以节约很多时间完成很复杂的工作。但通过perl threads模块的描述文件可以看到,它也有很多缺点。比如说在使用perl多线程的时候,必须的保证所有引用的模块都是支持thread。而在实际应用中,我们很难做到这样。比如我们要多线程,但同时要应用OLE模块去操作activex。 此用例应该是一种很常见的用例。那是不是意味着此时我们不得不放弃使用多线程呢。 非也, 本文介绍一种可以使用多线程和ole的例子。

     在http://www.cpan.org/官方网站上对这种情况给出的方案是:

    If the module will only be used inside a thread, you can try loading the module from inside the thread entry point function using require (and import if needed):

         sub thr_func
    {
    require Unsafe::Module
    # Unsafe::Module->import(...);
    ....
    }

          If the module is needed inside the main thread, try modifying your application so that the module is loaded (again using require and ->import()) after any threads are started, and in such a way that no other threads are started afterwards。

    再次,主要讨论一下第二种情况,既主要是该非thread模块放到方法中引用。下面是一个demo。


    use threads;
    use threads::shared;
    use Thread::Queue;
    no warnings 
    'threads';

    # Time 
    out const
    my $TIMEOUT : shared;
    $TIMEOUT 
    = 1;
    # the sig 
    for end thread 
    my $TERM : shared;
    $TERM 
    = 0;
    #my $excel;

    $SIG{
    'INT'= $SIG{'TERM'= sub{ print("\n>>> Terminating <<<\n"); $TERM=1;};
    $SIG{
    'KILL'= sub{ printf("%3d <- Killed\n", threads->tid()); 
                        threads
    ->detach() if !threads->is_detached();
                        threads
    ->exit(); };

    sub ThreadWatcher
    {
        my $queue 
    = shift;
        my 
    %timers;
        
        
    while(!$TERM)
        {
            #print 
    "ThreadWatcher -- TERM : $TERM\n";
            
    while(my $tid = $queue->dequeue_nb())
            {
                
    if (! defined($timers{$tid}{'timeout'= $queue->dequeue()) ||
                    
    ! defined($timers{$tid}{'thread'}  = threads->object($tid)))
                {
                    # No timeout 
    - unregister thread
                    delete($timers{$tid});
                }
            }
                   
            
            
    foreach my $tid (keys(%timers))
            {
                #print 
    "$timers{$tid}{'thread'} \n";
                
    if(--$timers{$tid}{'timeout'< 0)
                {
                    print 
    "thread $timers{$tid}{'thread'} will be killed.\n";
                    $timers{$tid}{
    'thread'}->kill('KILL');
                    delete($timers{$tid});
                }
            }
            
            # tick tock
            sleep(
    1);
        }
    }

    sub Worker
    {
        #eval {use Win32::OLE::Variant;};
        
        my ($queue, $dataqueue) 
    = @_;
        # 
    get the thread id and register with watch
        my $tid 
    = threads->tid();
        printf(
    "Working -> %3d\n", $tid);
        $queue
    ->enqueue($tid, $TIMEOUT);
        print 
    "Worker -- TERM : $TERM\n";
        
    while(!$TERM)
        {
            
            #my $App 
    = $dataqueue->dequeue();
            my $data 
    = $dataqueue->dequeue();
            #deal with the data
            #print 
    "Worker -- DATA : $App\n";
            print 
    "Worker -- DATA : $data\n";
            
            #my $var 
    = Win32::OLE::Variant->new(VT_BSTR, $data);
            #print 
    "Worker VAR: $var\n";
        }
        
        # Remove signal handler
        $SIG{
    'KILL'= sub {};

        # Unregister with timer thread
        $queue
    ->enqueue($tid, undef);

        # Tell user we
    're done
        printf("%3d <- Finished\n", $tid);
       
        threads
    ->detach() if ! threads->is_detached();
        threads
    ->exit();
    }

    # create time thread

    my $watchQueue 
    = Thread::Queue->new();
    threads
    ->create('ThreadWatcher', $watchQueue)->detach();

    # create work thread
    my $dataQueue 
    = Thread::Queue->new();
    threads
    ->create('Worker', $watchQueue, $dataQueue);

    NoneSafeModelScript(
    'C:\Joe_Chen\Perl_Projects\Threads\update.xlsx');

    WairLongTime(
    10);


    sub WairLongTime
    {
        my $temp 
    = $_[0];
        $temp 
    = $temp * 10000000;
        
    for(my $index = 0; $index < $temp; $index++)
        {
            $index 
    * $index;
        }
        
    return $index;
    }

    sub NoneSafeModelScript
    {
        eval 
    'use Win32::OLE';  
        eval 
    'use Win32::OLE::Variant';
        
        my $excel;
        
    for(my $index = 0; $index < 600; $index++)
        {
            print 
    "Getting the Excel ActiveObject. Try # $index \n";
            WairLongTime(
    1);
            eval
            {
                $excel 
    = Win32::OLE->GetActiveObject('Excel.Application'|| Win32::OLE->new('Excel.Application''Quit');
            };
            
    if($@ or $excel == undef)
            {
                print 
    "Unsuccessful: $@ \n";
                
    if($index == 599)
                {
                    print 
    "ERROR:Don\'t got the Excel Application";
                }
            }
            
    else
            {
                last;
            }
        }
        
        my $path 
    = $_[0];
        
        my $book 
    = $excel->workbooks->open($path);
        my $sheet 
    = $book->worksheets(1);
        
        my $values 
    = $sheet->Range("A1:D5")->{Value};
        my $row_counts 
    = $sheet->Range("A1:C3")->{Rows}->{Count};
        my $column_counts 
    = $sheet->Range("A1:C3")->{Columns}->{Count};
            
        print 
    "NoneSafeModelScript : $row_counts \n";
        print 
    "NoneSafeModelScript : $column_counts \n";
        
        
    for(my $row=1; $row<$row_counts + 1; $row++)
        {
            my $array_ref 
    = $sheet->Cells($row,1)->{Value};
            print 
    "NoneSafeModelScript : $array_ref \n";
            
            my $var 
    = Variant(Win32::OLE::Variant->VT_BSTR, $array_ref);
            my $v 
    = ref($var);
            #my $v 
    = $var->Type();
            print 
    "NoneSafeModelScript VAR: $var\n";
            print 
    "NoneSafeModelScript VAR: $v\n";
            #$dataQueue
    ->enqueue($var);
            $dataQueue
    ->enqueue($array_ref);
            WairLongTime(
    2);
        }
        
        my $v 
    = Variant(VT_DATE, "April 1 99");
        print $v
    ->Type, "\n";
        print $v
    ->Date(DATE_LONGDATE), "\n";
        print $v
    ->Date("ddd',' MMM dd yy"), "\n";
        
        print Win32::OLE::Variant
    ->VT_BSTR , "\n";
        
        $book
    ->Close;
        $excel
    ->Quit;
    }

    sub Wrap
    {
        my $value 
    = $_[0];
        my $var 
    = Variant(VT_DATE, 'Jan 1,1970');
        print 
    "Wrap : $var \n"
        
    return $var;
    }

    在此例子中,用到了queue,它的作用是将非thread 安全的数据通过管道传输,这样能避免他们互相调用。

  • 相关阅读:
    常用的知识点
    2021年度“新时代好少年”
    音频格式TDM
    DTS
    学习总结之EXTJS相关了解和问题解决篇
    java中extends和implements的区别
    开发
    程序员练级(转自酷壳)
    优秀程序员无它善假于物也
    EXTJS开发过程遇到的一些问题的小结(转自麦田守望者)
  • 原文地址:https://www.cnblogs.com/licheng/p/1612325.html
Copyright © 2011-2022 走看看