[英]Running a Thread every minute OR another condition
I need to run a thread every minute to clean up a table in a DB, I'm using a sleep(1000) inside a while(true) loop. 我需要每分钟运行一个线程来清理数据库中的表,我在while(true)循环中使用了sleep(1000)。 However, I need to clean up the same table if a List's size is bigger than X. I really can't find out how to make that. 但是,如果List的大小大于X,则需要清理同一张表。我真的不知道如何做到这一点。 (except the sleep(1000) way) can you guys please help me? (sleep(1000)方式除外)你们能帮我吗?
Here's my code: 这是我的代码:
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();
}
}
}
}
And here where I start my thread: 在这里我开始我的线程:
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;
}
}
How can I alter this so I can add the condition to start the thread when the idList size is bigger than X? 我该如何更改它,以便在idList大小大于X时添加条件以启动线程?
I would look into the ScheduledExecutorService and have it periodically execute a Runnable. 我将调查ScheduledExecutorService并定期执行Runnable。 For example, the following code should run your "run" method form your TrxJanitor every minute: 例如,以下代码应每分钟从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);
}
}
You should use a monitor for this task. 您应该为此任务使用监视器。
It allows you to wait for a specific time on a monitor (note that it has a wait with a timeout overload), the trick is that while you are waiting on a monitor- the wait can be interrupted in two cases- either the time elapses or somebody calls notify on the monitor object. 它允许您在监视器上等待特定的时间(请注意,它有一个超时过载的等待),窍门是,当您在监视器上等待时,该等待可能在两种情况下被中断-时间已流逝或有人打电话通知在监视器对象上。
A basic usage example: 基本用法示例:
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();
Have a look at this answer for a more elaboration. 请看一下这个答案以进行更详细的说明。
您可以像Minh Nguyen建议的那样创建ScheduledExecutorService
,但是使用此答案中所述的逻辑来根据您不断变化的需求重新安排任务的时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.