当前位置: 首页 > 知识库问答 >
问题:

当线程太少,程序挂起

陆子默
2023-03-14

当为-t=17-fn=15运行以下程序时,程序将在合理的时间内停止。这意味着最大线程数大于写入并并发缓存的文件数。

按要求更新:当$perl6--profile con test时分析器输出。p6-t=7-fn=5

When-t

当程序运行时间为-t=17-fn=20--hack时,程序将在合理的时间内运行完成。

我不知道下面的程序是否失败,因为我在CompUnit中遇到了一个问题,或者是否有一个线程(或其他)问题我丢失了。

假设存在某种线程情况,并且文件的数量必须小于线程的数量,那么重写hack的最佳方法是什么。目前,一个数组中充满了promise,然后允许遵守这些promise。但是wait要求在清空数组并重新填充之前保留所有这些元素。我认为,无论如何,这应该被重新写为一个渠道或供应。然而,我不太清楚如何做到这一点。

提前谢谢。

use v6.c;
use nqp;
use File::Directory::Tree;

my Lock $lock;
my $precomp;
#assume a writable directory files/

sub MAIN(:$t=5, :$fn = 10, :$hack=False ) {
    PROCESS::<$SCHEDULER> = ThreadPoolScheduler.new(initial_threads => 0, max_threads => $t);

    rmtree '.test';
    empty-directory 'files';

    my $precomp-store = CompUnit::PrecompilationStore::File.new(prefix => '.test'.IO );
    $precomp = CompUnit::PrecompilationRepository::Default.new(store => $precomp-store);
    $lock .=new;
    my %files = |gather for ^$fn {
        my $f = "files/name_$_.pod6";
        $f.IO.spurt: data;
        take "name_$_" => %(:key(nqp::sha1($f)), :path($f))
    }
    my @compilations;
    my @compiled;
    for %files.kv -> $source, (:path($path), :key($key)) {
        @compilations.push: start compile( $source, $key, $path );
        if $hack {
           if @compilations.elems %% ($t - 2) {
              @compiled.append: await @compilations;
              @compilations = ()
          }
       }
    }
    @compiled.append: await @compilations;
    for @compiled {
        if .<error>.defined {
            say .<error>
        }
        else {
            say .<source> ~ ' compiled'
        }
    }
}

sub compile( $source, $key, $path ) {
    my ($handle , $error, $status );
    try {
        CATCH {
            default {
                $error = "Compile error in $source:\n\t" ~ .Str
            }
        }
        $lock.protect( {
            $precomp.precompile($path.IO, $key, :force );
            $handle = $precomp.load($key)[0];
        })
    }
    with $handle {
        $status = 'OK';
    }
    else {
        $status = 'Failed';
        $error = 'unknown precomp error' without $error; # make sure that $error is defined for no handle
    }
    %(:$error, :$status, :$source)
}

sub data(-->Str ) {
    q:to/DD/
    =begin pod :tag<self>

    =TITLE Community
    X<|Community>

    =SUBTITLE Information about the people working on and using Perl 6

    =head1 Overview

    "Perl 5 was my rewrite of Perl.  I want Perl 6 to be the community's rewrite
    of Perl and of the community." - Larry Wall

    =head1 The Perl 6 community

    There is a large presence on the C<#perl6> channel on C<freenode.net>,
    who are happy to provide support and answer questions. More resources can be found in the L<perl6.org community page|https://perl6.org/community/>. L<Camelia|https://perl6.org/>, the multi-color butterfly with P 6 in her wings, is the symbol of this diverse and welcoming community. We use extensively
    the L<C<#perl6>|https://perl6.org/community/irc> IRC channel for communication, questions and simply hanging out. Check out this L<IRC lingo|http://www.ircbeginner.com/ircinfo/abbreviations.html> resource for the abbreviations frequently used there.  L<StackOverflow|https://stackoverflow.com/questions/tagged/perl6> is also a great resource for asking questions and helping others with their Perl 6 problems and challenges.

    The Perl 6 community publishes every December an L<Advent Calendar|https://perl6advent.wordpress.com/>, with Perl 6 tutorials every day until Christmas. Organization and assignment of days is done through the different Perl 6 channels and the L<Perl6/mu|https://github.com/perl6/mu> repository. If you want to participate, it starts organization by the end of October, so check out the channels above for that.

    =end pod

    DD
}

共有1个答案

钱和安
2023-03-14

问题是,如果需要太多线程,那么程序将挂起,因此解决方法是创建一个队列,分配尽可能多的线程,然后当每个线程中的例程完成时,它将从队列中弹出数据。

下面我已经实现了这个策略,它处理线程数小于文件数的情况,而不会冻结。实际上,线程数必须比文件数少两个(参见if@thread

下面是对问题中带有队列的程序的重写。

#!/usr/bin/env perl6
use v6.d;
use nqp;
use File::Directory::Tree;

my Lock $lock;
my $precomp;
#assume a writable directory files/

sub MAIN(:$t=15, :$fn = 10 ) {
    say "Threads: $t, Files: $fn, Compiler:", $*PERL;
    PROCESS::<$SCHEDULER> = ThreadPoolScheduler.new(initial_threads => 0, max_threads => $t);

    rmtree '.test';
    empty-directory 'files';

    my $precomp-store = CompUnit::PrecompilationStore::File.new(prefix => '.test'.IO );
    $precomp = CompUnit::PrecompilationRepository::Default.new(store => $precomp-store);
    $lock .=new;
    my %files = |gather for ^$fn {
        my $f = "files/name_$_.pod6";
        $f.IO.spurt: data;
        take "name_$_" => %(:key(nqp::sha1($f)), :path($f))
    }
    my @compilations;
    my @compiled;
    my @threads; 
    for %files.kv -> $source, (:path($path), :key($key)) {
        @compilations.push: ( $source, $key, $path );
        @threads.push( start
            sub ( @queue ) {
                my @params = @queue.pop.list if @queue;
                return unless +@params;
                my $res = compile( |@params );
                $lock.protect({
                    @compiled.append: $res;
                });
                &?ROUTINE( @queue )
            }( @compilations )
        )  if +@threads < $t - 2;
    }
    await @threads;
    for @compiled {
        if .<error>.defined {
            say .<error>
        }
        else {
            say .<source> ~ ' compiled'
        }
    }
}

sub compile( $source, $key, $path ) {
    my ($handle , $error, $status );
    try {
        CATCH {
            default {
                $error = "Compile error in $source:\n\t" ~ .Str
            }
        }
        $precomp.precompile($path.IO, $key, :force );
        $handle = $precomp.load($key)[0];
    }
    with $handle {
        $status = 'OK';
    }
    else {
        $status = 'Failed';
        $error = 'unknown precomp error' without $error; # make sure that $error is defined for no handle
    }
    %(:$error, :$status, :$source)
}

sub data(-->Str ) {
    q:to/DD/
    =begin pod :tag<self>

    =TITLE Community
    X<|Community>

    =SUBTITLE Information about the people working on and using Perl 6

    =head1 Overview

    "Perl 5 was my rewrite of Perl.  I want Perl 6 to be the community's rewrite
    of Perl and of the community." - Larry Wall

    =head1 The Perl 6 community

    There is a large presence on the C<#perl6> channel on C<freenode.net>,
    who are happy to provide support and answer questions. More resources can be found in the L<perl6.org community page|https://perl6.org/community/>. L<Camelia|https://perl6.org/>, the multi-color butterfly with P 6 in her wings, is the symbol of this diverse and welcoming community. We use extensively
    the L<C<#perl6>|https://perl6.org/community/irc> IRC channel for communication, questions and simply hanging out. Check out this L<IRC lingo|http://www.ircbeginner.com/ircinfo/abbreviations.html> resource for the abbreviations frequently used there.  L<StackOverflow|https://stackoverflow.com/questions/tagged/perl6> is also a great resource for asking questions and helping others with their Perl 6 problems and challenges.

    The Perl 6 community publishes every December an L<Advent Calendar|https://perl6advent.wordpress.com/>, with Perl 6 tutorials every day until Christmas. Organization and assignment of days is done through the different Perl 6 channels and the L<Perl6/mu|https://github.com/perl6/mu> repository. If you want to participate, it starts organization by the end of October, so check out the channels above for that.

    =end pod

    DD
}

 类似资料:
  • 问题内容: 我正在用javaFx编写天气应用程序,以从openweather.org获取数据。从openweather获取JSON的整个代码运行良好,也可以将JSON数据转换为对象。我用lambda表达式来实现在。问题是:如果我运行Main class,请按按钮,该应用程序将挂起。导入数据的线程有效(在控制台上通过2次打印检查),主线程“跳过” 并在控制台上打印某些内容。我不确定这里出什么问题了。

  • 我正在使用在线程上运行的 SurfaceView 类中的画布。SurfaceView 由 Activity (setContentView(surfaceview)) 调用。当屏幕关闭时,它会通过一个 pause() 方法关闭所有循环变量等。 奇怪的是:虽然在我的平板电脑(Android 4.4.2)线程暂停和恢复正确(线程重新开始),但是在我的手机(Android 4.2.2)和其他人的手机(C

  • 问题内容: 我正在尝试的代码 我们如何根据其ID暂停/暂停线程?Thread.suspend已过时,必须有一些替代方法来实现。我有线程ID,我想挂起并杀死线程。 编辑:我用这个。 但是我无法停止该线程。 问题答案: 这些天杀死线程的正确方法就是使用它。这集真和原因,以及一些其他的方法来扔。 在线程代码内部,您应该执行类似以下的操作,检查以确保它没有被中断。 这是一个如何在线程内部处理中断异常的示例

  • 问题内容: 我有一个python程序,可以打开一个套接字并提取ssl证书。它很好用,但是当我在某个IP范围内运行它时,程序不会通过线程140进行处理。有没有办法查看为什么它没有进行处理? 这是程序的线程部分 问题答案: 我不知道为什么它不起作用,但是我编写了一个模块,可以在文件的开头导入该模块: 它将显示线程挂起的位置,您可以进一步调试。

  • 问题内容: 我正在使用来自Guava的ListenableFuture,关于它们的一件好事是,将Executor传递给该方法,即要求在给定的线程/执行器上执行回调。 在我的Android应用程序中,我希望能够基于UI线程启动异步执行,并计划一个也在UI线程上执行的回调。因此,我想以某种方式将UI线程执行器提交给上述方法。如何实现呢? 或者,换句话说,我想要UI线程的执行程序。它已经在Android

  • 问题内容: 我遇到了程序挂起的情况,看起来像死锁。但是我尝试用jconsole和visualvm来解决这个问题,但是他们没有发现任何死锁。样例代码: 当我在调试模式下执行此操作时,我可以看到控件达到@Override public void run(){state = 11; 但是一旦执行state = 11,它就会挂起/死锁。我在stackoverflow中查看了不同的帖子,我认为静态初始化程序