在单独的单个线程中为JavaFX排队打印作业
目前我正在Java/JavaFX中试验并发性。打印必须在不同的线程中运行,否则会使JavaFX主线程冻结几秒钟。现在,我的打印是用这个简化的示例完成的在单独的单个线程中为JavaFX排队打印作业,java,multithreading,javafx,concurrency,queue,Java,Multithreading,Javafx,Concurrency,Queue,目前我正在Java/JavaFX中试验并发性。打印必须在不同的线程中运行,否则会使JavaFX主线程冻结几秒钟。现在,我的打印是用这个简化的示例完成的 public void print(PrintContent pt) { setPrintContent(pt); Thread thread = new Thread(this); thread.start(); } @Override public void run() { // send content
public void print(PrintContent pt) {
setPrintContent(pt);
Thread thread = new Thread(this);
thread.start();
}
@Override
public void run() {
// send content to printer
}
有了这段代码,我将许多打印作业并行发送到我的打印机。因此,我得到的错误告诉我,我的打印机一次只能处理一个打印作业。因为我知道线程不能重用,所以我想知道是否有可能对线程进行排队,以便我的打印机一次只处理一个打印作业
非常感谢您的努力和时间。使用a执行打印作业。它将创建一个且仅一个后台线程,并将作业排队:
// it might be better not to make this static; but you need to ensure there is
// only one instance of this executor:
private static final Executor PRINT_QUEUE = Executors.newSingleThreadExecutor();
// ...
public void print(PrintContent pt) {
PRINT_QUEUE.execute(() -> {
// send content to printer
});
}
使用来执行打印作业。它将创建一个且仅一个后台线程,并将作业排队:
// it might be better not to make this static; but you need to ensure there is
// only one instance of this executor:
private static final Executor PRINT_QUEUE = Executors.newSingleThreadExecutor();
// ...
public void print(PrintContent pt) {
PRINT_QUEUE.execute(() -> {
// send content to printer
});
}
路1
您可以实现自己的BlockingQueue或使用Java库中的默认实现
因此,在阅读了以上链接之后,您在类中添加了一个方法,如
public void addJob(Object job){
queue.put(job);
}
其次,您实现了一个运行在无限while循环中的线程
queue.take();
当队列为空时,此线程将被阻塞,等待添加新对象,因此您不必担心花费cpu时间
最后,您可以设置一些上限,例如队列可以包含。。27个项目
提到在线程失败的情况下,您必须手动重新创建它
~~>WAY 2更好的方法
您可以使用Executors接口:
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
从文件:
创建一个执行器,该执行器使用单个辅助线程在
无限队列。但是请注意,如果此单线程终止
由于关机前执行过程中出现故障,将出现新的故障
如果需要执行后续任务,则替换它。任务是
保证按顺序执行,并且最多只能执行一个任务
在任何给定时间都处于活动状态
如果作业已成功完成,则使用下面的方法检索结果
Future future = executorService.submit(new Callable(){ public Object call() throws Exception { System.out.println("Asynchronous Callable"); return "Callable Result"; } });
System.out.println("future.get() = " + future.get());
如果future.get返回null,则表示作业已成功完成
记得打电话
执行器服务关闭;因为此ExecutorService中的活动线程可能会阻止JVM关闭
完整教程
路1
您可以实现自己的BlockingQueue或使用Java库中的默认实现
因此,在阅读了以上链接之后,您在类中添加了一个方法,如
public void addJob(Object job){
queue.put(job);
}
其次,您实现了一个运行在无限while循环中的线程
queue.take();
当队列为空时,此线程将被阻塞,等待添加新对象,因此您不必担心花费cpu时间
最后,您可以设置一些上限,例如队列可以包含。。27个项目
提到在线程失败的情况下,您必须手动重新创建它
~~>WAY 2更好的方法
您可以使用Executors接口:
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
从文件:
创建一个执行器,该执行器使用单个辅助线程在
无限队列。但是请注意,如果此单线程终止
由于关机前执行过程中出现故障,将出现新的故障
如果需要执行后续任务,则替换它。任务是
保证按顺序执行,并且最多只能执行一个任务
在任何给定时间都处于活动状态
如果作业已成功完成,则使用下面的方法检索结果
Future future = executorService.submit(new Callable(){ public Object call() throws Exception { System.out.println("Asynchronous Callable"); return "Callable Result"; } });
System.out.println("future.get() = " + future.get());
如果future.get返回null,则表示作业已成功完成
记得打电话
执行器服务关闭;因为此ExecutorService中的活动线程可能会阻止JVM关闭
完整教程请注意,除了向打印机发送多个打印作业的问题外,代码还存在多个线程试图访问相同状态的问题。通过调用setPrintContentpt每次调用打印。。。将printContent设置为不同的值;您创建的线程将在将来的某个不确定点尝试访问该值。不能保证后台线程会看到正确的打印内容。你完全正确。我遇到异常,特别是当我在很短的时间内连续发送2个或更多打印作业时。这不会导致异常,只会导致打印错误的内容。例外情况来自您已识别的问题。请注意,除了向打印机发送多个打印作业的问题外,您的代码还存在多个线程试图访问相同状态的问题。通过调用setPrintContentpt每次调用打印。。。将printContent设置为不同的值;您创建的线程将在将来的某个不确定点尝试访问该值。不能保证后台线程会看到正确的打印内容。你完全正确。我是
获取异常,特别是当我在很短的时间内连续发送2个或更多打印作业时。这不会导致异常,只会导致打印错误的内容。例外情况来自您已经确定的问题。您好,GoXr3Plus,感谢您的提示。在阅读有关Executer的文章时,我也遇到了BlockingQueue。你能告诉我为什么你会认为Executer是更好的方法,或者这两种方法之间的主要区别是什么吗?@Chiggidi Executor实现在内部使用某种阻塞队列。我想告诉你如何实现你自己的。毕竟,使用第二种方法只是一些代码行,而不是实现你的您需要知道的基本上都在链接上。@Chiggiddi执行器和阻塞队列之间的区别是什么?执行者执行可运行文件。阻塞队列只是将项目放置在队列中,但不处理它们。单线程执行器在单线程上执行runnable,正如GoXr3Plus所述,当一个runnable必须等待另一个runnable完成时,它在内部使用阻塞队列。因此,基本上,单线程执行器为您实现了上面的方式1,并且做了很多工作,例如处理可运行程序的故障等@James_D Hi guys,今天我实现了executor服务,它通过测试运行得非常好。您能告诉我,执行器Singelton执行Runnable的顺序是否基于FIFO,因此进入执行器的第一个Runnable将首先执行吗?如中所述,它由队列支持。根据定义,队列是FIFO。因此,如果两个要执行的调用之间存在一个before关系,那么在第一个调用中传递给execute的Runnable保证在第二个调用中传递给execute的Runnable之前执行。您好,GoXr3Plus,感谢您的提示。在阅读有关Executer的文章时,我也遇到了BlockingQueue。你能告诉我为什么你会认为Executer是更好的方法,或者这两种方法之间的主要区别是什么吗?@Chiggidi Executor实现在内部使用某种阻塞队列。我想告诉你如何实现你自己的。毕竟,使用第二种方法只是一些代码行,而不是实现你的您需要知道的基本上都在链接上。@Chiggiddi执行器和阻塞队列之间的区别是什么?执行者执行可运行文件。阻塞队列只是将项目放置在队列中,但不处理它们。单线程执行器在单线程上执行runnable,正如GoXr3Plus所述,当一个runnable必须等待另一个runnable完成时,它在内部使用阻塞队列。因此,基本上,单线程执行器为您实现了上面的方式1,并且做了很多工作,例如处理可运行程序的故障等@James_D Hi guys,今天我实现了executor服务,它通过测试运行得非常好。您能告诉我,执行器Singelton执行Runnable的顺序是否基于FIFO,因此进入执行器的第一个Runnable将首先执行吗?如中所述,它由队列支持。根据定义,队列是FIFO。因此,如果两个要执行的调用之间存在一个before关系,那么第一个调用中传递给execute的Runnable保证在第二个调用中传递给execute的Runnable之前执行。