perl share filehandle with threads

时光总嘲笑我的痴心妄想 提交于 2019-12-06 16:26:06

问题


I've found the code below online, it seems the way the program control the loop is to check the shared variable $TERM is 0 or not. Can I share a filehandle between threads, that every thread deal with one line of a file and loop ends when the file reaches the last line?

#!/usr/bin/perl

use strict;
use warnings;

use threads 1.39;
use threads::shared;
use Thread::Queue;

### Global Variables ###

# Maximum working threads
my $MAX_THREADS = 10;

# Flag to inform all threads that application is terminating
my $TERM :shared = 0;

# Threads add their ID to this queue when they are ready for work
# Also, when app terminates a -1 is added to this queue
my $IDLE_QUEUE = Thread::Queue->new();


### Signal Handling ###

# Gracefully terminate application on ^C or command line 'kill'
$SIG{'INT'} = $SIG{'TERM'} =
    sub {
        print(">>> Terminating <<<\n");
        $TERM = 1;
        # Add -1 to head of idle queue to signal termination
        $IDLE_QUEUE->insert(0, -1);
    };


### Main Processing Section ###
MAIN:
{
    ### INITIALIZE ###

    # Thread work queues referenced by thread ID
    my %work_queues;

    # Create the thread pool
    for (1..$MAX_THREADS) {
        # Create a work queue for a thread
        my $work_q = Thread::Queue->new();

        # Create the thread, and give it the work queue
        my $thr = threads->create('worker', $work_q);

        # Remember the thread's work queue
        $work_queues{$thr->tid()} = $work_q;
    }


    ### DO WORK ###

    # Manage the thread pool until signalled to terminate
    while (! $TERM) {
        # Wait for an available thread
        my $tid = $IDLE_QUEUE->dequeue();

        # Check for termination condition
        last if ($tid < 0);

        # Give the thread some work to do
        my $work = 5 + int(rand(10));
        $work_queues{$tid}->enqueue($work);
    }


    ### CLEANING UP ###

    # Signal all threads that there is no more work
    $work_queues{$_}->enqueue(-1) foreach keys(%work_queues);

    # Wait for all the threads to finish
    $_->join() foreach threads->list();
}

print("Done\n");
exit(0);


### Thread Entry Point Subroutines ###

# A worker thread
sub worker
{
    my ($work_q) = @_;

    # This thread's ID
    my $tid = threads->tid();

    # Work loop
    do {
        # Indicate that were are ready to do work
        printf("Idle     -> %2d\n", $tid);
        $IDLE_QUEUE->enqueue($tid);

        # Wait for work from the queue
        my $work = $work_q->dequeue();

        # If no more work, exit
        last if ($work < 0);

        # Do some work while monitoring $TERM
        printf("            %2d <- Working\n", $tid);
        while (($work > 0) && ! $TERM) {
            $work -= sleep($work);
        }

        # Loop back to idle state if not told to terminate
    } while (! $TERM);

    # All done
    printf("Finished -> %2d\n", $tid);
}

回答1:


Can I share a filehandle between threads

No.

that every thread deal with one line of a file and loop ends when the file reaches the last line?

Yes. Just feed the lines from the file instead of numbers to the worker threads.

By the way, you don't need 11 queues to do that. You just need one:

#!/usr/bin/perl

use strict;
use warnings;

use threads 1.39;
use threads::shared;
use Thread::Queue qw( );

# Maximum working threads
my $NUM_WORKERS = 10;

# Flag to inform all threads that application is terminating
my $TERM :shared = 0;

my $request_q = Thread::Queue->new();

$SIG{INT} = $SIG{TERM} = \&signal_handler;

exit(main());

sub signal_handler {
    print(">>> Terminating <<<\n");
    $TERM = 1;
}    

sub main {
    my @threads;
    push @threads, threads->create(\&worker)
        for 1..$NUM_WORKERS;

    while (!$TERM && defined(my $job = <>)) {
        chomp($job);
        $request_q->enqueue($job);
    }

    # Signal to threads that there is no more work.
    $q->enqueue(undef) for 1..$NUM_WORKERS;

    # Wait for all the threads to finish.
    $_->join() for @threads;

    print("Done\n");
    return 0;
}

sub worker {
    my $tid = threads->tid();

    while (!$TERM && defined(my $job = $request_q->dequeue())) {
        printf("            %2d <- Working\n", $tid);

        # Do something with $job.
        sleep(1+rand(3));
    }

    printf("Finished -> %2d\n", $tid);
}


来源:https://stackoverflow.com/questions/12696375/perl-share-filehandle-with-threads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!