2010-07-04 78 views
2

這是一個比特定問題更通用的問題。我試圖讓多線程環境保持活動狀態,以便我可以提交任務並運行它們。我想在沒有在Web服務器或應用程序服務器中執行的麻煩的情況下執行此操作。這個想法是爲此使用java線程池,但問題在於,池直到我的主方法完成時才保持打開狀態,之後顯然它關閉並且程序結束。我怎樣才能防止這種情況發生?我確信有幾個選擇,比其他人更天真(而真正的循環想到)。 任何想法?謝謝。java線程池繼續運行

+0

你想主要終止和你的線程繼續運行? – 2010-07-04 13:11:37

+0

你如何向你的應用程序提交任務? – naikus 2010-07-04 14:33:14

+0

你不是在製作守護線程嗎? – 2010-07-05 16:19:27

回答

1

如何您的任務被接受?

在很多情況下,我看到有1個線程正在等待或輪詢任務並將其傳遞。該線程將保持應用程序的活動狀態,並且還可以等待某個標誌關閉應用程序,等待當前作業完成並清理。總而言之,我發現處理這些應用程序生命週期事件的麻煩已經超過了部署到像Jetty這樣的簡單容器的麻煩,這一點很容易達成。特別是對於在後臺運行的東西,我發現在幾個愚蠢的JSP頁面中有很多價值來驗證它仍然在工作(與我們的自動監視集成)並獲取一些統計信息。

-1

什麼你definitly可以做的是一個循環是這樣的:

while (true) { 
    Thread.sleep(1000); 
} 

如果你wan't停止過程中,你殺了它。然而,這不是一個優雅的解決方案

更好的方式是,聽一些端口上,等到您在該端口上得到一些命令:

ServerSocket socket = new ServerSocket(4444); 
while (true) { 
    Socket clientSocket = socket.accept(); 
    // get input stream, etc. 
    // if(STOP keywoard read) break 
} 
0

以下是我爲另一篇文章撰寫的示例,該文章允許您在另一個線程上提供可以發佈消息的線程池。 main()創建線程並允許您在需要時停止線程。要停止main完成,只需刪除processor.stopProcessing();主線。

package com.rch.test; 

import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.LinkedBlockingQueue; 
import java.util.concurrent.TimeUnit; 

public class Executor 
{ 
    /** 
    * Class to encapsulate a request 
    * 
    * @author romain 
    */ 
    static class Request 
    { 
     String someText; 

     Request(String someText) 
     { 
      this.someText = someText; 
     } 

     public String getSomeText() 
     { 
      return someText; 
     } 
    } 

    /** 
    * Creates a Thread that listens on a queue to process messages 
    * 
    * @author romain 
    */ 
    static class ServerThread implements Runnable 
    { 
     private BlockingQueue<Request> queue = new LinkedBlockingQueue<Request>(); 
     volatile boolean stop = false; 

     /** 
     * Does all the work 
     */ 
     @Override 
     public void run() 
     { 
      ExecutorService pool = Executors.newFixedThreadPool(3); 
      try 
      { 
       while (!stop) 
       { 
        Request req = queue.poll(1000L, TimeUnit.MILLISECONDS); 
        if (req != null) 
        { 
         Runnable runnable = new Executor.ImageProcessor(req); 
         pool.execute(runnable); 
        } 
       } 
      } 
      catch (InterruptedException ie) 
      { 
       System.out.println("Log something here"); 
      } 
      finally 
      { 
       pool.shutdown(); 
      } 
     } 

     /** 
     * Accepts a message on the queue 
     * @param request 
     */ 
     public void accept(Request request) 
     { 
      queue.add(request); 
     } 

     public void stopProcessing() 
     { 
      stop = true; 
     } 
    } 

    /** 
    * class to do the actual work 
    * @author romain 
    */ 
    static class ImageProcessor implements Runnable 
    { 
     String someText; 

     ImageProcessor(Request req) 
     { 
      this.someText = req.getSomeText(); 
     } 

     @Override 
     public void run() 
     { 
      System.out.println(someText); 
      // Process Image here 
     } 
    } 

    /** 
    * Test Harness 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
     // Initialize 
     ServerThread processor = new ServerThread(); 
     Thread aThread = new Thread(processor); 
     aThread.start(); 

     // Wait for Thread to start 
     try 
     { 
      Thread.sleep(500L); 
     } 
     catch (InterruptedException e1) 
     { 
      e1.printStackTrace(); 
     } 

     for (int i = 0; i < 100; i++) 
     { 
      String text = "" + i; 
      Request aRequest = new Request(text); 
      processor.accept(aRequest); 
     } 

     // Give it enough time to finish 
     try 
     { 
      Thread.sleep(500L); 
     } 
     catch (InterruptedException e1) 
     { 
      e1.printStackTrace(); 
     } 

     // Tell the thread to finish processing 
     processor.stopProcessing(); 

     // Wait for the Thread to complete 
     try 
     { 
      aThread.join(); 
     } 
     catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

至少,字段'ServerThread#stop'需要聲明* volatile *。 – seh 2010-07-04 13:44:03

+0

@seh並非如此,我只有一個可以在我的示例中寫入的線程和一個可以從中讀取的線程。我不關心線程安全性,也不關心它被緩存了一段時間。無論如何,讀取或寫入布爾值是原子。 – 2010-07-04 14:01:46

+1

你的位置的重要部分不關心,如果「[布爾字段]被緩存一段時間」。它可以被緩存 - 因此對於想要「中斷」的線程永遠不可見。儘管分配布爾型字段可能會「原子地」發生 - 因爲沒有讀者可以看到「部分值」 - 跨線程邊界的寫入*傳播受到很大的影響,您不應該舉一個例子取決於傳播而不注意或消除漏洞。 – seh 2010-07-04 18:18:02

0

這是我在一些程序中在main()的末尾調用的一些代碼。如果用戶在命令行中輸入「quit」,程序將清除並退出。否則,如果用戶輸入「操作」來執行其他操作,則可以修改位置。

public void serve() throws IOException 
    { 
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
     PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 
     String line = null; 

     for (;;) 
     { 
     out.print("> "); 
     out.flush(); 
     line = in.readLine(); 
     if (line == null) 
     { 
      break;     // QUIT if we get EOF 
     } 

     try 
     { 
      // Use a stringTokenizer to parse the user's command 
      StringTokenizer t = new StringTokenizer(line); 

      // blank line 
      if (!t.hasMoreTokens()) 
      { 
       continue; 
      } 

      // get the first word of the input and convert to lower case 
      String command = t.nextToken().toLowerCase(); 

      if (command.equals("quit")) 
      { 
       bTerminate = true; 
       // Do all cleanup here 
       myClient.close(); 
       break; 
      } 
      else if (command.equals("action")) 
      { 
       if (line.length() > command.length()) 
       { 
        // get data from rest of line 
        String data = line.substring(command.length()).trim(); 
        // perform action 
        myOutputStream.writeUTF(data); 
       } 
      } 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
     } 
     out.close(); 
     in.close(); 
    } 
-1
public class Test extends Thread { 

    private static Test thread1, thread2, thread3; //static added since tested from main() 

    public static void main(String... arguments){ 
    try{  
     thread1 = new Test(); 
     thread2 = new Test(); 
     thread3 = new Test(); 
     // Add Names 
     thread1.setName("A"); 
     // Add Sleep 
     thread2.sleep(2000); //in milisecs - here it is 2sec 
     // Add priority 
     thread3.setPriority(Thread.MAX_PRIORITY); 

     // Infinite loop 
     while(true){  
      thread1.start(); 
      thread2.start(); 
      thread3.start();  
     } 
    }catch(Throwable t){ 
     System.err.println(t.getMessage()); 
    } 
} 

    public void run() { 
     System.out.println(Thread.currentThread().getName()); 
    } 
}