I created a schedule work with scheduleAtFixedRate, and the thread I set 2 ways to execute, 1、
Thread.sleep(10000);
Thread.sleep(200);
when I run this code, it will execute with a 2s delay, but when a==3, the thread sleep 10s, and then, there will exclude 5 thread immediately, How can I just run 1 thread but not 5?
public class Words {
private int a =0;
public void init(){
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
Date d = new Date();
SimpleDateFormat sbf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
System.out.println(sbf.format(d));
try {
if (a == 3) {
Thread.sleep(10000);
} else {
Thread.sleep(200);
}
a += 1;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 2, TimeUnit.SECONDS);
}
public static void main(String[] args) {
Words words = new Words();
words.init();
}
}
Maybe the thread will execute very long, but I don't want the scheduleAtFixedRate to execute a lot of threads like the phenomenon I've said, How can the scheduleAtFixedRate just run 1 thread? thank you
Related
ScheduledExecutorService is still running after calling its shutdown methos from class's shutdown method below.
I was not expecting to see perioudRun's call after shutdown
Running the method shutdown
Running the method periodicRun-
What should I do ensure, the schedule run is cancelled ?
class test {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
test() {
scheduler.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
funcA("periodicRun-");
}
}, 15, 15, TimeUnit.SECONDS);
}
private void funcA(String path) {
LOGGER.info("Running the method " + path)
}
public void shutdown() {
long startTimeMs = System.currentTimeMillis();
scheduler.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!scheduler.awaitTermination(initialTerminationSeconds, TimeUnit.SECONDS)) {
scheduler.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
scheduler.awaitTermination(retryTerminationSeconds,
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
scheduler.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
funcA("shutdown-");
}
}```
The code you provided does not compile. I made some corrections and some assumptions where it did not compile, and the following code works as expected, i.e. "periodicRun" is not printed after shutdown() is called:
class Test {
public static void main(String[] args) {
Test test = new Test();
test.test(); // CALL TEST METHOD
Thread t = new Thread(() -> {
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
test.shutdown(); // CALL SHUTDOWN METHOD
});
t.start();
}
private final int initialTerminationSeconds = 1;
private final int retryTerminationSeconds = 1;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
void test() {
scheduler.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
funcA("periodicRun-");
}
}, 15, 15, TimeUnit.SECONDS);
}
private void funcA(String path) {
System.out.println("Running the method " + path);
}
public void shutdown() {
long startTimeMs = System.currentTimeMillis();
scheduler.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!scheduler.awaitTermination(initialTerminationSeconds, TimeUnit.SECONDS)) {
scheduler.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
scheduler.awaitTermination(retryTerminationSeconds, TimeUnit.SECONDS);
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
scheduler.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
funcA("shutdown-");
}
}
As this code works as expected, the problem in your code is either somewhere else or the assumptions and corrections I made to your code are incorrect.
This is my code for a card deck on a table, I've never used Threads before and don't know how to use.
I need them to show up with a 2s delay between each of them.
Initially all the cards are .setVisible(false);
try {
Card1.setVisible(true);
Thread.sleep(2000);
Card2.setVisible(true);
Thread.sleep(2000);
Card3.setVisible(true);
Thread.sleep(2000);
Card4.setVisible(true);
Thread.sleep(2000);
Card5.setVisible(true);
Thread.sleep(2000);
Card6.setVisible(true);
Thread.sleep(2000);
Card7.setVisible(true);
Thread.sleep(2000);
Card8.setVisible(true);
Thread.sleep(2000);
Card9.setVisible(true);
Thread.sleep(2000);
Card10.setVisible(true);
}
catch (InterruptedException ex) {
Logger.getLogger(TableController.class.getName()).log(Level.SEVERE, null, ex);
}
It's not a multi-threading issue.
But you can achieve this by storing the Card objects in a List and the iterating it.
List<Card> cardsList = new ArrayList<>();
cardsList.add(Card1);
...
cardsList.add(Card10);
try {
for(Card card : cardsList) {
card.setVisible(true);
Thread.sleep(2000);
}
} catch (InterruptedException ex) {
Logger.getLogger(TableController.class.getName()).log(Level.SEVERE, null, ex);
}
You can use a Timer, this will handle your multi-threading and let actions take place with at scheduled times.
long delay = 2000;
Timer timer = new Timer();
timer.schedule( new TimerTask(){
#Override
public void run(){
Card1.setVisible(true);
}
}, delay);
timer.schedule( new TimerTask(){
#Override
public void run(){
Card2.setVisible(true);
}
}, delay*2);
The first task will run after 2000ms delay, the second task after 4000ms delay. I stopped there because it is cumbersome to write everything out. You should consider using a list as the other answer suggested.
Incidentally, the timer will manage a thread for you. I think your actual problem was you were blocking the EDT
We can use DelayQueue for printing result with some delay.
Code Example:
public static void main(String... args) throws InterruptedException {
DelayQueue<DeleyedItem> dq = new DelayQueue();
DeleyedItem ob1 = new DeleyedItem(TimeUnit.SECONDS.toMillis(2), Card1);
DeleyedItem ob2 = new DeleyedItem(TimeUnit.SECONDS.toMillis(4), Card2);
DeleyedItem ob3 = new DeleyedItem(TimeUnit.SECONDS.toMillis(6), Card3);
dq.offer(ob1);
dq.offer(ob2);
dq.offer(ob3);
while (!dq.isEmpty()) {
DeleyedItem item = dq.take();
item.visible();
}
}
}
class DeleyedItem implements Delayed {
public final Long delayMillis;
public final Long expireTimeMillis;
private Card card;
DeleyedItem(long delayMillis,Card card) {
this.delayMillis = delayMillis;
this.expireTimeMillis = System.currentTimeMillis() + delayMillis;
this.card=card;
}
#Override
public final int compareTo(Delayed o) {
long diffMillis = getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS);
diffMillis = Math.min(diffMillis, 1);
diffMillis = Math.max(diffMillis, -1);
return (int) diffMillis;
}
#Override
public final long getDelay(TimeUnit unit) {
long delayMillis = expireTimeMillis - System.currentTimeMillis();
return unit.convert(delayMillis, TimeUnit.MILLISECONDS);
}
public void visible() {
card.setVisible(true);
}
You can use lockSupport util to park the thread for certain time.
public static void main(String[] args) {
Card1.setVisible(true);
await(2, TimeUnit.SECONDS);
Card2.setVisible(true);
await(4, TimeUnit.SECONDS);
Card3.setVisible(true);
}
public static void await(long time, TimeUnit unit) {
LockSupport.parkNanos(unit.toNanos(time));
}
I want to execute a thread periodically to check if some file is ready for uploaded and upload it as soon as it is ready then stop the thread immediately. Also, if a long time has passed I want to stop the thread regardless the file not being ready, but can't do it inside the run method itself.
final ScheduledFuture<?> fileUploadedFuture = scheduler.scheduleAtFixedRate(() -> {
try {
if (fileReady("xyz.txt")) {
uploadFile("xyz.txt")
//cancel fileUploadedFuture and fileUploadedFutureCanceller
}
} catch (Exception e) {
throw new ServiceException(e);
}
}, 0, delay, TimeUnit.SECONDS);
final ScheduledFuture<?> fileUploadedFutureCanceller = scheduler.schedule(() -> {
fileUploadedFuture.cancel(true);
}, 60, TimeUnit.SECONDS);
}
How about using a ScheduledThreadPoolExecutor?
public class TestExecutor {
private static ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
private static class PushFile implements Runnable {
#Override
public void run() {
if (new File("test.txt").exists()) {
System.out.println("found it!");
exec.shutdown();
} else {
System.out.println("waiting");
}
}
}
private static class ShutMeDown implements Runnable {
#Override
public void run() {
System.out.println("timeout");
exec.shutdown();
}
}
public static void main(String[] args) {
exec.scheduleWithFixedDelay(new PushFile(), 0, 1, TimeUnit.SECONDS);
exec.scheduleWithFixedDelay(new ShutMeDown(), 10, 1, TimeUnit.SECONDS);
}
}
#laughing buddha suggested a watcher. It's probably more resource-efficient than my first suggestion, but I'm not entirely sure it's the right solution in this case, because you're still parking a thread. Nevertheless, I coded a test, and it's short and easy to read, so you may as well have the code:
public class TestWatchService {
public static void main(String[] args) throws IOException, InterruptedException {
WatchService watcher = FileSystems.getDefault().newWatchService();
Path file = Paths.get(".");
WatchKey key = file.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
List<WatchEvent<?>> events = new ArrayList<>();
for (boolean done = false; ! done; events = key.pollEvents()) {
if (events.size()==0) {
System.out.println("waiting");
Thread.sleep(2000L);
} else {
System.out.println("got it!");
done = true;
}
}
}
}
I am using single thread executor for long-running threads like this:
executor = Executors.newSingleThreadExecutor(THREAD_FACTORY);
executor.submit(new LongRunnable());
which checks a flag to be stopped:
private class LongRunnable implements Runnable {
#Override
public void run() {
while (isRunning.get()) {
try {
doSomething();
} catch (InterruptedException e) {
...
}
}
}
}
and whole execution is interrupted that way:
#Override
public void close() throws Exception {
isRunning.set(false);
executor.shutdownNow();
}
Still I can see some threads not gc-ed in profiler (while by logs, runnable they were executing has quit outermost while loop).
Question: does provided working with threads strategy memory-leak-free and thread-leak-free?
I am not able to see any issue with executor or shutDownNow. Probably you are looking at different threads in your profiler.
Try this program which is similar to the one in your question and you can see the thread is no longer there after successful shutdown.
public class ExecutorShutdownTest {
private static ExecutorService executor;
private static AtomicLong executorThreadId = new AtomicLong(0);
public static void main(String[] args) {
// get thread MX bean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// create an executor and start the task
executor = Executors.newSingleThreadExecutor(new TestThreadFactory());
LongRunnable runnable = new LongRunnable();
executor.submit(runnable);
// main thread: keep running for sometime
int count = 5;
while (count-- > 0) {
try {
Thread.sleep(1000);
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace(
"\n", ""));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// main thread: stop the task
try {
runnable.close();
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace("\n", ""));
} catch (Exception e) {
e.printStackTrace();
}
// main thread: run some more time to verify the executor thread no longer exists
count = 5;
while (count-- > 0) {
try {
Thread.sleep(1000);
System.out.println(String.valueOf(threadMXBean.getThreadInfo(executorThreadId.longValue())).replace("\r", "").replace("\n", ""));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static class LongRunnable implements Runnable {
private volatile boolean isRunning = true;
#Override
public void run() {
while (isRunning) {
System.out.println("Running");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//ignore
}
}
System.out.println("Stopped");
}
public void close() throws Exception {
System.out.println("Stopping");
isRunning = false;
executor.shutdownNow();
}
}
private static class TestThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
TestThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0) {
#Override protected void finalize() throws Throwable {
super.finalize();
// probably bad idea but lets see if it gets here
System.out.println("Executor thread removed from JVM");
}
};
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
executorThreadId.set(t.getId());
System.out.println("Executor thread created");
return t;
}
}
}
Here's a sample program using the single-thread Executor that manages to strand a thread so that the JVM can't shut down, but it only manages to do it by not calling shutdownNow:
import java.util.concurrent.*;
public class Exec {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new MyTask());
Thread.sleep(20000L);
// executor.shutdownNow();
int retryCount = 4;
while (!executor.isTerminated() && retryCount > 0) {
System.out.println("waiting for tasks to terminate");
Thread.sleep(500L);
retryCount -= 1;
}
}
}
class MyTask implements Runnable {
public void run() {
int count = 0;
try {
while (!Thread.currentThread().isInterrupted() && count < 10) {
Thread.sleep(1000L);
count += 1;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("all done");
}
}
The thread used by the executor has a separate life cycle from the task, this example shows how the task finishes but the thread goes on. Uncommenting the shutdownNow results in the executor's thread terminating. Otherwise the main thread sleeps for a while and exits, leaving the executor's thread hanging out, preventing the JVM from exiting.
My guess is that your close method isn't getting called and your executor never gets shut down. To get more useful answers please add a MVCE so that we can reproduce the problem.
Consider that with interruption there's no need to keep a reference to the Runnable to set the flag. As I read the question the task not finishing is not an issue here, but it would still be better to make the Runnable respond to interruption and lose the flag, just because having less things to keep track of is always an improvement.
I have a requirement threading where I need to initiate a thread which will run continuously doing some DB operations . A second thread will be present which needs to run for every 30 secs. The job of the second thread will be killing the first thread and start a new instance of the first thread.
I tried several ways to achieve this but I am not able to do the same.
public class ThreadMain {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException{
final CyclicBarrier gate = new CyclicBarrier(3);
Thread t1 = new Thread(){
public void run(){
try {
gate.await();
while(true)
{
System.out.println("Thread1");
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
Thread t2 = new Thread(){
public void run(){
try {
gate.await();
while(true)
{
System.out.println("Continiously running thread:-Thread2");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
t1.start();
t2.start();
This seems to work nicely:
// Thread that runs forever.
volatile static Thread forEverThread = null;
static class ForEver implements Runnable {
#Override
public void run() {
try {
while (true) {
Thread.sleep(1000);
System.out.println("For Ever!");
}
} catch (InterruptedException ex) {
// Just quit if I was interrupted.
}
}
}
// Stop the thread if it is running.
private static void stopForeverThread() throws InterruptedException {
// Skip if non-existent.
if (forEverThread != null) {
// Make sure no-one else is already doing it.
synchronized (forEverThread) {
// Still not null?
if (forEverThread != null) {
// Interrupt it.
forEverThread.interrupt();
// Wait for it to finish.
forEverThread.join();
// Clear it.
forEverThread = null;
}
}
}
}
private static void restartForeverThread() throws InterruptedException {
System.out.println("Restarting...");
// Stop it if it is running.
stopForeverThread();
// Start it again.
forEverThread = new Thread(new ForEver());
forEverThread.start();
System.out.println("Restarted");
}
public static void start() throws InterruptedException {
// Start it all up.
restartForeverThread();
// Timed event to restart it.
Timer restartTimer = new Timer(true);
restartTimer.scheduleAtFixedRate(
new TimerTask() {
#Override
public void run() {
try {
// Restart every few seconds.
restartForeverThread();
} catch (InterruptedException ex) {
// We were interrupted during restart - Log it.
}
}
// Every few seconds.
}, 0, 10 * 1000);
}
public static void main(String args[]) {
try {
// Start it all up.
start();
// Hang around for a while - to see what happens.
Thread.sleep(60 * 1000);
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
If your database task is interruptible (i.e. it reacts on thread interruption and hence can be cancelled by that), the best strategy is to use an ScheduledExecutorService for both, the database task itself and the restart task that runs periodically.
Note that task and thread are two different things: While a task is a piece of work that should be run, threads are the mechanism to do this in parallel.
static class DatabaseTask implements Runnable {
public void run() {
...
}
}
static class RestartTask implements Runnable {
private final ExecutorService executor;
private volatile Future<Void> future;
public RestartTask(ExecutorService executor) {
this.executor = executor;
}
public void run() {
if (future != null) {
future.cancel(true);
}
future = executor.submit(new DatabaseTask());
}
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new RestartTask(executor), 0, 30, TimeUnit.SECONDS);
Note that if your DatabaseTask is NOT sensitive to thread interruption and continues to perform database operations, the number of threads executing database tasks will grow continously - probably not what you want. So make sure, all blocking database operations are either interruptible, or terminate within a reasonable amount of time.