好的,我创建了几对线程来完成一些复杂的任务。现在我如何检查每个线程是否已成功完成?
class BrokenTasks extends Thread {
public BrokenTasks(){
super();
}
public void run(){
//Some complex tasks related to Networking..
//Example would be fetching some data from the internet and it is not known when can it be finished
}
}
//In another class
BrokenTasks task1 = new BrokenTasks();
BrokenTasks task2 = new BrokenTasks();
BrokenTasks task3 = new BrokenTasks();
BrokenTasks task4 = new BrokenTasks();
task1.start();
.....
task4.start();
那么如何检查这些所有任务是否成功完成 i)主程序(主线程) ii)从每个连续的线程。例如:检查task1是否已经从task2中结束..
答案 0 :(得分:2)
使用线程的好方法是不直接使用它们。而是创建一个线程池。然后在您的POJO任务封装中有一个仅在计算结束时设置的字段。
当另一个线程可以看到状态时,可能会有3-4毫秒的延迟 - 但最终JVM就这样做了。只要其他线程不会过度写入它。您可以通过确保每个任务具有要执行的唯一工作实例和状态来保护,而其他线程仅每1-5秒轮询一次,或者具有工作程序在完成后调用的侦听器。 我用过的图书馆是我自己的 https://github.com/tgkprog/ddt/tree/master/DdtUtils/src/main/java/org/s2n/ddt/util/threads
使用:在服务器启动或静态块中:
package org.s2n.ddt.util;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.s2n.ddt.util.threads.PoolOptions;
import org.s2n.ddt.util.threads.DdtPools;
public class PoolTest {
private static final Logger logger = Logger.getLogger(PoolTest.class);
@Test
public void test() {
PoolOptions options = new PoolOptions();
options.setCoreThreads(2);
options.setMaxThreads(33);
DdtPools.initPool("a", options);
Do1 p = null;
for (int i = 0; i < 10; i++) {
p = new Do1();
DdtPools.offer("a", p);
}
LangUtils.sleep(3 + (int) (Math.random() * 3));
org.junit.Assert.assertNotNull(p);
org.junit.Assert.assertEquals(Do1.getLs(), 10);
}
}
class Do1 implements Runnable {
volatile static long l = 0;
public Do1() {
l++;
}
public void run() {
// LangUtils.sleep(1 + (int) (Math.random() * 3));
System.out.println("hi " + l);
}
public static long getLs() {
return l;
}
}
你不该做的事情: *不要每10-15毫秒做一次事 *除非学术不做自己的线程 *不要让它变得更复杂,然后需要97%的案例
答案 1 :(得分:2)
您可以使用Callable
和ForkJoinPool
执行此任务。
class BrokenTasks implements Callable {
public BrokenTasks(){
super();
}
public Object call() thrown Exception {
//Some complex tasks related to Networking..
//Example would be fetching some data from the internet and it is not known when can it be finished
}
}
//In another class
BrokenTasks task1 = new BrokenTasks();
BrokenTasks task2 = new BrokenTasks();
BrokenTasks task3 = new BrokenTasks();
BrokenTasks task4 = new BrokenTasks();
ForkJoinPool pool = new ForkJoinPool(4);
Future result1 = pool.submit(task1);
Future result2 = pool.submit(task2);
Future result3 = pool.submit(task3);
Future result4 = pool.submit(task4);
value4 = result4.get();//blocking call
value3 = result3.get();//blocking call
value2 = result2.get();//blocking call
value1 = result1.get();//blocking call
在此之后不要忘记关闭池。
答案 2 :(得分:1)
您可以使用Thread.isAlive
方法,请参阅API:“如果线程已经启动且尚未死亡,则该线程处于活动状态”。这是在task2 run()中测试task1.isAlive()
要从task2查看task1,你需要将它作为参数传递给task2的construtor,或者创建任务字段而不是本地变量
答案 3 :(得分:1)
如果一个线程尚未完成其任务,那么它仍处于活动状态。因此,为了测试线程是否已完成其任务,您可以使用isAlive()
方法。
答案 4 :(得分:1)
通常,您只需加入要完成的主题即可。在加入完成之前,您的线程不会继续。例如:
// await all threads
task1.join();
task2.join();
task3.join();
task4.join();
// continue with main thread logic
(我可能会把这些任务放在一个清单处理的清单中)
答案 5 :(得分:1)
一个是线程是否仍在工作 另一个是如果任务仍未完成。
线程是解决问题的一种非常昂贵的方法,当我们在java中启动一个线程时,VM必须存储上下文信息并解决同步问题(例如锁定)。所以我们通常使用线程池而不是直接线程。线程池的好处是我们可以使用很少的线程来处理许多不同的任务。这意味着很少有线程可以保持活动状态,而许多任务都已完成。
线程是一个工人,任务就是工作 一个线程可以逐个处理许多不同的工作 我认为我们不应该问工人是否已经完成了工作。如果完成,我宁愿问工作。
当我想检查作业是否完成时,我会使用信号。
有许多同步辅助工具,因为JDK 1.5就像信号一样工作。
CountDownLatch此对象提供一个计数器(只能设置一次并倒计数多次)。此计数器允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
CyclicBarrier这是另一个有用的信号,它允许一组线程等待彼此达到共同的障碍点。
可以在JDK java.util.concurrent
包中找到更多工具。
答案 6 :(得分:0)
You can use the following..
task1.join();
task2.join();
task3.join();
task4.join();
// and then check every thread by using isAlive() method
e.g : task1.isAlive();
if it return false means that thread had completed it's task
otherwise it will true
答案 7 :(得分:0)
我不确定您的确切需求,但是一些Java应用程序框架在处理单个工作单元或“工作”方面具有方便的抽象。 Eclipse Rich Client平台考虑了其Jobs API。虽然它可能有点矫枉过正。
对于普通的旧Java,请查看Future,Callable和Executor。