这是一个比特定问题更通用的问题。我试图让多线程环境保持活动状态,以便我可以提交任务并运行它们。我想在没有在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