繁体   English   中英

每分钟或其他情况下运行一个线程

[英]Running a Thread every minute OR another condition

我需要每分钟运行一个线程来清理数据库中的表,我在while(true)循环中使用了sleep(1000)。 但是,如果List的大小大于X,则需要清理同一张表。我真的不知道如何做到这一点。 (sleep(1000)方式除外)你们能帮我吗?

这是我的代码:

public class TrxJanitor implements Runnable {

    private Thread t;
    private List<UUID> idList;

    public List<UUID> getIdList() {
        return idList;
    }

    /* getters and setters*/

       public void start()
       {
          if (t == null)
          {
             t = new Thread(this);
             t.start();
          }
       }

    public void addToJanitorList(UUID id){
        idList.add(id);
    }

    @Override
    public void run() {                 
            System.out.println("Running...");
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("account-pu");                    
            while (true) {
            // create EM tx1 and tx2
                EntityManager em = emf.createEntityManager();

                em.getTransaction().begin();

                System.out.println("Trying to delete from DB...");
                if(!idList.isEmpty()) {
                    for (UUID id : idList) {                
                        em.createNativeQuery("DELETE FROM TrxIdList WHERE Id LIKE '"+id+"'").executeUpdate();
                        System.out.println("DELETED THIS ID: "+id );
                    }
                    idList.removeAll(idList);
                }
                em.getTransaction().commit();
                System.out.println("DATA IN DB:\n");

              // print all lines of table
                @SuppressWarnings("unchecked")
                List<TrxIdList> ids = em.createNativeQuery("SELECT * FROM TrxIdList", TrxIdList.class).getResultList();
                if (!ids.isEmpty()) {
                    System.out.println("DB ROWS:\n");
                    int i = 0;
                    for (TrxIdList id : ids)
                    {
                         System.out.println("TRX_ID: "+id.getId() + " DATA: "+ id.getCreationTs()+"\n");
                         i++;
                    }
                    System.out.println("There are still a total of "+i+" lines in this table!");
                }

                em.close();

                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

    }


}

在这里我开始我的线程:

public class PopulateTrxIdTable {

    public static void main(String[] args) {

        TrxJanitor t = new TrxJanitor();
        t.start();
        System.out.println("All records inserted!");        
        System.out.println("Going to sleep!");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {          
                e.printStackTrace();
            }
        System.out.println("Waking up!");       
        System.out.println("DONE!");
        System.out.println("Inserting into DB...");

        insertIntoDb(t);
    }

    private static void insertIntoDb(TrxJanitor t) {

        boolean pair = true;
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("account-pu");

        // create EM 
        EntityManager em1 = emf.createEntityManager();

        em1.getTransaction().begin();

        for (int i=0; i< 10000; i++) {
        //populates DB with the values returned by fillIds()
            if(i%2==0){
                pair = true;
            } else {
                pair = false;
            }
            em1.persist(fillIds(t, pair));

        }
        em1.getTransaction().commit();
        em1.close();
        emf.close();
    }

    private static TrxIdList fillIds(TrxJanitor j, boolean pair) {

        TrxIdList p = new TrxIdList();
        Random rand = new Random();

        //populates de DB with random ids and random dates (dates within range)        
        int randomNum = rand.nextInt((10 - 0) + 1) + 0;
        UUID id = UUID.randomUUID();    
        p.setId(id.toString());
        p.setCreationTs(notToday(randomNum)); //notToday returns a random timestamp
        if (pair) {
            j.addToJanitorList(id);
        }
        return p;

    }

}

我该如何更改它,以便在idList大小大于X时添加条件以启动线程?

我将调查ScheduledExecutorService并定期执行Runnable。 例如,以下代码应每分钟从TrxJanitor运行您的“ run”方法:

 import static java.util.concurrent.TimeUnit.*;
 public class PopulateTrxIdTable {
   private final ScheduledExecutorService scheduler =
     Executors.newScheduledThreadPool(1);

   public static void main(String[] args) {
     scheduler.schedule(new TrxJanitor(), 1, SECONDS);
   }
 }

您应该为此任务使用监视器。

它允许您在监视器上等待特定的时间(请注意,它有一个超时过载的等待),窍门是,当您在监视器上等待时,该等待可能在两种情况下被中断-时间已流逝或有人打电话通知在监视器对象上。

基本用法示例:

final Object mon = new Object();

// This thread waits on a monitor for 1000msec, unless the other guy wakes him up first...
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            System.out.println("Sleep 1000");
            synchronized (mon) {
                mon.wait(1000);
            }
        } catch (InterruptedException e) { }
    }
}).start();

// this thread will flip a coin and wake up the waiting thread if it hits tails
new Thread(new Runnable() {
    @Override
    public void run() {
        if (new Random().nextBoolean()) {
            System.out.println("Wake early!");
            synchronized (mon) {
                mon.notify();
            }
        }
    }
}).start();

请看一下这个答案以进行更详细的说明。

您可以像Minh Nguyen建议的那样创建ScheduledExecutorService ,但是使用此答案中所述的逻辑来根据您不断变化的需求重新安排任务的时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM