2

我有一个任务 x 在一个线程中连续执行,只有当布尔值将其状态更改为 true 时才会停止。我已经阅读了一些内容,并且在杀死下面代码中的线程时,我可以采用 3 种方法。3种方法哪一种有效?如果它们都不是有效或不正确的,请建议一个适当的方法和一些代码供参考。

下面是代码:

public class MyTest {

private static class transaction {

     private String param1,param2,param3, param4, param5;

     public transaction (String param1,String param2,String param3,String param4,String param5){
         this.param1=param1;
         this.param2=param2;
         this.param3=param3;
         this.param4=param4;
         this.param5=param5;
     }

     public String getParam1(){
         return this.param1;
     }

     public String getParam2(){
         return this.param2;
     }

     public String getParam3(){
         return this.param3;
     }

     public String getParam4(){
         return this.param4;
     }

     public String getParam5(){
         return this.param5;
     }
}

public static void processBatch(String workerName){

    try{

        java.util.List <transaction> transactions= new java.util.LinkedList<transaction>();
        java.sql.ResultSet dbtrx=Database.db.execQuery((Object)"dbname.procname");

        while(dbtrx.next()){// Takes a snapshot of the pending payments in the table and stores it into the list.
            Object obj=new transaction (dbtrx.getString("col1"), dbtrx.getString("col2"), dbtrx.getString("col3"), dbtrx.getString("col4"), dbtrx.getString("col5"));
            transactions.add((transaction)obj);
            obj=null;
        }

        java.util.Iterator<transaction> iterate= transactions.iterator();

        /* Processes the pending batch payments*/
        while(iterate.hasNext()){
            transaction trx=iterate.next();
            /*Calls posting function here*/
            System.out.println(workerName+":- Param1 : "+trx.getParam1()+" - Param2 : " +trx.getParam2()+
                    " - Param3 : "+ trx.getParam3()+" - Param4 : "+ trx.getParam4()+" - Param5 : "+ trx.getParam5());
            iterate.remove();
        }

        /*cleaning object references*/
        dbtrx=null;
        transactions=null;
        iterate=null;

     }catch(Exception e){
        e.printStackTrace();
     }
}

public static void main(String [] args) throws InterruptedException{
    volatile boolean stop=false;
    Object hold= new Object();
    new Thread("Batch Worker A"){
        @Override 
        public void run(){
            while(true){
                if(stop!=true){
                    processBatch(Thread.currentThread().getName());
                }else{
                    try{
                    Thread.sleep(0);
                    Thread.currentThread().interrupt();
                    }catch(java.lang.InterruptedException e){
                        Thread.currentThread().interrupt(); 
                        break;
                    }
                }
            }
        }}.start();

    new Thread("Batch Worker B"){
        @Override 
        public void run(){
            try{
                while(stop!=true){
                    processBatch(Thread.currentThread().getName());
                }
                Thread.sleep(0);
                Thread.currentThread().interrupt();
            }catch(java.lang.InterruptedException e){
                Thread.currentThread().interrupt(); 
            }
        }}.start();

    new Thread("Batch Worker C"){
        @Override 
        public void run(){
            while(!Thread.currentThread().isInterrupted()){
                if(stop!=true){
                    processBatch(Thread.currentThread().getName());
                }else{
                    Thread.currentThread().interrupt();
                }
            }
        }}.start();
    }
}

}

4

3 回答 3

6

推荐的方法是使用线程的中断标志来通知线程循环终止。没有理由在一个可以使用的地方使用两个标志(stopped和中断标志),而且您似乎没有将中断标志用于其他任何事情。

有关更广泛的讨论和示例,请参阅 Java 教程主题中断。

于 2013-02-04T09:20:01.770 回答
3

为什么不简单地这样:

new Thread("Batch Worker A"){
    @Override 
    public void run() {
        while(!stop){
                processBatch(Thread.currentThread().getName());
            }
        }
    }}.start();

或者,Thread.interrupt()像这样使用:

new Thread("Batch Worker A"){
    @Override 
    public void run() {
        while(!interrupted()){
                processBatch(Thread.currentThread().getName());
            }
        }
    }}.start();

但是你需要保持对所有线程的引用,并将它们全部中断,所以布尔标志可能更简单(一定要让它变得易变)。

于 2013-02-04T09:23:00.070 回答
1

在您的所有示例中,您并没有真正杀死线程,而是在阻止批处理处理更多项目。要了解差异,请注意,当线程位于 processBatch 函数中时,您的任何方法都不会真正停止线程。

有几点需要注意:

  • 在当前线程上调用 Interrupt() 毫无意义。中断背后的想法是让外部线程调用它。在您的情况下,您也可以抛出异常,或从 run() 函数返回(这将自动关闭线程)。
  • 如果线程在java之外被锁定,即使interrupt()在许多情况下也不能停止线程,例如线程等待IO(如果不使用NIO),包括一个套接字,这是数据库连接,你需要设计一种不同的方式来停止 IO 内的线程(通常通过超时,但还有其他方式)。

如果您的目标只是阻止下一批发生,请使用 Joonas 的代码:

new Thread("Batch Worker A"){
@Override 
public void run() {
    while(!stop){
            processBatch(Thread.currentThread().getName());
        }
    }
}}.start();

如果您的目标是在运行批处理时中断该过程,您也可以这样做:

public static void main(String[] args) {
   var t =new Thread("Batch Worker A"){
      @Override 
      public void run() {
         processBatch(Thread.currentThread().getName());
       }
   }.start(); 
   t.interrupt();
}

一般来说,中断是首选方法,使用局部范围变量和匿名类是一个非常糟糕的主意(使用静态变量,或者更好地使用带有函数的注入接口来检查线程是否应该继续)。

于 2013-02-04T09:43:31.927 回答