3

我是 perl 的新手,正在尝试多线程。我期待下面的程序创建所有线程并至少在 5 秒后打印“创建所有线程”,一旦执行并且所有线程都在等待输入值。

use threads;

my @arr = (1,2,3,4);
foreach (@arr) {
    sleep(1);
    print "\ncreating...\n";
    threads->new(\&echo, $_);
    print "\ncreated\n";
}
print "\ncreated all the threads\n";
sleep(200); #wait for the threads to finish

sub echo {
    my ($thread) = @_;
    print "\nthread($thread) Enter the value:\n";
    my $value = <>;
    print "\nthread($thread) Got value= $value\n";
}

但我得到了关注:

creating...

created

thread(1) Enter the value:

creating...

似乎还没有创建其他 3 个线程,如果我删除 sleep(1),我有时会得到预期的结果,但是涉及 sleep(1),即使等待几分钟,我也会得到上述结果。我可能会错过什么?我认为这是基本的东西,但我无法弄清楚。

更新:

相同的程序在 Linux 上完美运行,Windows 的平台特定问题可能是什么?

更新2:

在同一行上遵循 java 程序在同一个盒子上工作得很好:

import java.io.IOException;


public class MT {

    public static void main(String[] args)throws Exception {
        for(int i=0;i<4;i++){
            Thread.sleep(2000);
            new Thread(new Task(i)).start();
        }
        System.out.println("created all the threads");
        Thread.sleep(20000);

    }

    static class Task implements Runnable{

        int i;
        public Task(int i) {
            super();
            this.i = i;
        }
        @Override
        public void run() {
            try {
                System.out.println("Thread:"+i+" Enter value");
                int x= System.in.read();
                System.out.println(x);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

我不确定 perl 如何在 Windows 上支持多线程!

4

1 回答 1

2

您实际上有两个不同的阻塞问题:

  1. 控制台上的 I/O 缓冲(感谢 Disco 3 的建议)。
  2. 从标准输入读取的线程相互阻塞(但不是其他线程)。

考虑这个测试程序:

use threads;
 $| = 1;

my $thr1 = threads->new(\&echo, 1);
my $thr2 = threads->new(\&print_dots, 2);
sleep 10;
my $thr3 = threads->new(\&echo, 3);

sleep 200;



sub print_dots {
    while (1) {
        print ".";
        sleep 1;
    }
}

sub echo {

    my ($thread) = @_;
    print "\nthread($thread) Enter the value:\n";
    sleep 1;
    my $value = <>;
    print "\nthread($thread) Got value= $value\n";
}

如果您不禁用 i/o 缓冲(由 完成$|=1;),那么您根本不会得到任何点。如果禁用输入缓冲,打印点的线程永远不会被阻塞。但是,从控制台读取的第二个线程仍然被第一个线程阻塞。

如果您需要在 Windows 上的 Perl 中从标准输入进行真正的非阻塞读取,有一些潜在的解决方案。 Win32::Console可能是一个很好的起点。这是一个可能有用的讨论

于 2012-10-16T14:12:57.963 回答