2012-10-16 75 views
3

我是新來的Perl和嘗試多線程。我期待以下程序創建所有線程,並至少在5秒後打印「創建所有線程」,一旦執行並且所有線程等待輸入值。Perl中的多線程程序在窗口上給出意外的結果

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"; 
} 

但我得到以下outout:

creating... 

created 

thread(1) Enter the value: 

creating... 

似乎其他3個線程尚未創建的,如果我刪除了睡眠(1)我得到有時預期的結果,但與睡眠(1)涉及,甚至等待幾分鐘,我得到了上述結果。我可能錯過了什麼?我認爲這是基本的,但我無法弄清楚。

UPDATE:

同樣的程序在Linux上工作完美無瑕,這可能是針對Windows平臺的具體問題?

UPDATE2:

在同一行以下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上支持多線程的窗口!

+0

有趣。你的代碼適用於我(Linux上的V5.12.4)。你在運行什麼操作系統? –

+0

同樣在這裏:FreeBSD 8.3上的Perl 5.14.2,它就像一個魅力。然後同樣的問題:你在什麼操作系統?一些Windows? – Ouki

+0

這是Deja Vu,很多時候當我問一些關於perl問題的問題時,第一個評論是'它在我的Linux機器上運行,您使用的是什麼操作系統?' :),我假設perl是平臺獨立的。無論如何,我在Windows 2008框中運行此草莓perl 5,版本16,Subversion 0(v5.16.0)爲MSWin32-x86-多線程構建。確實是 – Sushant

回答

2

你實際上有兩種不同的封閉問題:控制檯上

  1. I/O緩衝(感謝迪斯科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可能是一個很好的開始。 Here is a potentially useful discussion

+0

實際上,問題來自網絡代碼(測試用例),我想在其中啓動2個偵聽某個端口和兩個不同線程的套接字和一個將它們從主線程連接起來的客戶端,我最好使用非阻塞套接字,也許是'select',但是這確實違背了多線程的一個目的,即即使其中一個線程被阻塞,該進程也不應該被阻塞在某些操作中,以便其他線程可以繼續執行其他線程,更好地處理線程之間的上下文切換而不是進程 – Sushant

+0

@Sushant,阻塞問題可能更具體於您正在執行的操作類型,而不是一般線程。相信套接字和控制檯I/O在Win32上都有阻塞問題,但它們可能不一樣。您可能需要問一個特定於套接字的問題以獲得有關您的pr的幫助oblem。 – dan1111