這是一個比特定問題更通用的問題。我試圖讓多線程環境保持活動狀態,以便我可以提交任務並運行它們。我想在沒有在Web服務器或應用程序服務器中執行的麻煩的情況下執行此操作。這個想法是爲此使用java線程池,但問題在於,池直到我的主方法完成時才保持打開狀態,之後顯然它關閉並且程序結束。我怎樣才能防止這種情況發生?我確信有幾個選擇,比其他人更天真(而真正的循環想到)。 任何想法?謝謝。java線程池繼續運行
回答
如何您的任務被接受?
在很多情況下,我看到有1個線程正在等待或輪詢任務並將其傳遞。該線程將保持應用程序的活動狀態,並且還可以等待某個標誌關閉應用程序,等待當前作業完成並清理。總而言之,我發現處理這些應用程序生命週期事件的麻煩已經超過了部署到像Jetty這樣的簡單容器的麻煩,這一點很容易達成。特別是對於在後臺運行的東西,我發現在幾個愚蠢的JSP頁面中有很多價值來驗證它仍然在工作(與我們的自動監視集成)並獲取一些統計信息。
什麼你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
}
以下是我爲另一篇文章撰寫的示例,該文章允許您在另一個線程上提供可以發佈消息的線程池。 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();
}
}
}
至少,字段'ServerThread#stop'需要聲明* volatile *。 – seh 2010-07-04 13:44:03
@seh並非如此,我只有一個可以在我的示例中寫入的線程和一個可以從中讀取的線程。我不關心線程安全性,也不關心它被緩存了一段時間。無論如何,讀取或寫入布爾值是原子。 – 2010-07-04 14:01:46
你的位置的重要部分不關心,如果「[布爾字段]被緩存一段時間」。它可以被緩存 - 因此對於想要「中斷」的線程永遠不可見。儘管分配布爾型字段可能會「原子地」發生 - 因爲沒有讀者可以看到「部分值」 - 跨線程邊界的寫入*傳播受到很大的影響,您不應該舉一個例子取決於傳播而不注意或消除漏洞。 – seh 2010-07-04 18:18:02
這是我在一些程序中在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();
}
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());
}
}
- 1. OpenMP運行線程,但繼續主線
- 2. 畢加索線程繼續運行
- 3. Excel進程繼續運行
- 4. 線程池運行爲了
- 5. NetLogo:繼續運行
- 6. 執行器線程在熱部署後繼續運行
- 7. 主線程終止後進程繼續運行?
- 8. 服務被android關閉後線程是否繼續運行?
- 9. QtConcurrent ::在創建新線程後繼續運行
- 10. 是否線程繼續運行時的Future.get(超時)超時
- 11. 繼續在後臺運行次要線程
- 12. c#線程繼續與套接字運行
- 13. Java線程運行
- 14. 在``C``線程池中運行'POSIX`線程在``C``線程池中運行`函數指針`
- 15. 程序在終止後繼續運行
- 16. 關閉後繼續運行程序
- 17. 線程池是否按順序運行?
- 18. 從java運行一個.exe文件並繼續運行
- 19. 內存不足以使Java運行時環境繼續運行
- 20. Java程序繼續運行,沒有編譯器的錯誤
- 21. 在調用System.exit(0)後應用程序繼續運行 - Java
- 22. 的Java執行器服務線程池
- 23. 輸出繼續運行
- 24. 進度條繼續運行
- 25. DirectX 11 D3DXMatrixTranslation繼續運行?
- 26. Python腳本繼續運行
- 27. 從java中的線程池運行靜態方法
- 28. Java線程池大小(Executors)
- 29. Java - 重用線程池
- 30. Java中的線程池
你想主要終止和你的線程繼續運行? – 2010-07-04 13:11:37
你如何向你的應用程序提交任務? – naikus 2010-07-04 14:33:14
你不是在製作守護線程嗎? – 2010-07-05 16:19:27