如何检查线程是否完成了任务?

时间:2015-03-04 13:34:15

标签: java multithreading

好的,我创建了几对线程来完成一些复杂的任务。现在我如何检查每个线程是否已成功完成?

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中结束..

8 个答案:

答案 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)

您可以使用CallableForkJoinPool执行此任务。

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。