Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在单独的单个线程中为JavaFX排队打印作业_Java_Multithreading_Javafx_Concurrency_Queue - Fatal编程技术网

在单独的单个线程中为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

目前我正在Java/JavaFX中试验并发性。打印必须在不同的线程中运行,否则会使JavaFX主线程冻结几秒钟。现在,我的打印是用这个简化的示例完成的

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之前执行。