Is it possible in standard java8 to execute multiple callables on single thread concurrently?
i.e. when one callable sleeps, start working on other callable.
My current experiment, which does not work:
ExecutorService executor = Executors.newSingleThreadExecutor();
List<Future> fs = new ArrayList<>();
for (int i = 0; i < 2; i++) {
final int nr = i;
fs.add(executor.submit(() -> {
System.out.println("callable-" + nr + "-start");
try { Thread.sleep(10_000); } catch (InterruptedException e) { }
System.out.println("callable-" + nr + "-end");
return nr;
}));
}
try { executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { }
Results in:
callable-0-start
callable-0-end
callable-1-start
callable-1-end
I want to have:
callable-0-start
callable-1-start
callable-0-end
callable-1-end
Notes:
I kind of expect an answer: "No it's not possible. This is not how threads work. Once thread is assigned to some executable code it runs until completion, exception or cancellation. There can be no midflight-switching between callables/runnables. Thread.sleep only allows other threads to run on CPU/core." (explicit confirmation would put my mind to rest)
Naturally, this is "toy" example.
This is about understanding, not some specific problem that I have.
What you attempt to do is to emulate deprecated functionality from older java versions. Back then it was possible to stop, suspend or resume a Thread. But from the javadoc of Thread.stop:
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.
As described by this outtake, the risks of doing what you want were critical, and therefore this behavior has been deprecated.
I would suggest, that instead of trying to force a running thread into some sort of halting position from the outside, you should maybe think about a ThreadPool API that allows you to package your code segments properly, so that their state can be unloaded from a thread, and later resumed. e.g. create Ticket, which would be an elementary job, which a thread would always complete before beginning another, a TicketChain that sequentially connects tickets and stores the state. Then make a handler that handles tickets one by one. In case a Ticket cannot be currently done (e.g. because not all data is present, or some lock cannot be acquired) the thread can skip it until a later point in time, when said conditions might be true.
Building on answer from #TreffnonX
One way to achieve desired stdout result is using CompletableFuture
(callable code must be explicitly split into separate functions):
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletableFuture<Integer>[] fs = new CompletableFuture[2];
for(int i=0; i<2; i++) {
final Integer ii = i;
fs[i] = (CompletableFuture.completedFuture(ii)
.thenApply((Integer x) -> { System.out.println("callable-" + x + "-start");return x; })
.thenApplyAsync((Integer x) -> { try { Thread.sleep(1_000); } catch (InterruptedException e) {Thread.currentThread().interrupt();} return x; }, executor)
.thenApply((Integer x) -> { System.out.println("callable-" + x + "-end");return x; }));
}
CompletableFuture.allOf(fs).join();
try { executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { }
Result:
callable-0-start
callable-1-start
callable-0-end
callable-1-end
Related
I am writing the same code on tutorial. But in tutorial the program never exits, my in my computer it exits after 4 seconds. Why?
tutorial with exact time where this code is shown: https://youtu.be/vzBw1LPupnA?t=169
public class Main {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(() -> {
int i = 0;
while (!stopRequested) {
i++;
System.out.println("i = " + i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
The reason that you are seeing different behavior on your machine and in the video is because the program has unspecified behavior. (Or to put it another way, it is not thread-safe.)
You have two threads accessing and updating a shared variable without taking the necessary steps that will guarantee that changes made by one thread are visible to the other. What happens in that case is not specified.
In some cases (e.g. on some platforms) the changes will be visible, either immediately or within a short time.
On others, the changes may never be visible.
In technical terms, there must be a happens-before relationship between the write by on thread and the subsequent read by the other thread. This can be provided by both threads synchronizing on the same mutex or lock, by using a volatile variable, and in other ways. But this code doesn't do any of those things, so there is no guarantee that the state change will be visible.
For more details, read about the Java Memory Model.
The above is sufficient to explain the difference, but there may be a more direct explanation.
In practice, something like a System.out.println can lead to changes in the visibility. Underneath the covers, the println call will typically result in synchronization on the output stream's buffers. That can result in a serendipitous happens-before that is sufficient to guarantee visibility. But this behavior is not specified, so you should not rely on it.
At any rate, adding trace statements can change the behavior of multi-threaded coded. And the fact that you (apparently) added them in your version is a second possible explanation for the difference.
The bottom line here is that a program with a memory visibility flaw is broken, but you may not be able to demonstrate that it is broken.
As the excellent Answer by Stephen C says, your code is not thread-safe.
Establishing an AtomicBoolean early on addresses the visibility problem explained in that other Answer. This class is a thread-safe wrapper around its payload boolean value.
The volatile keyword is another solution. But I find the Atomic… classes simpler and more obvious.
Also, in modern Java we rarely need to address the Thread class directly. Instead, use the Executors framework. Define your task as a Runnable or Callable, and submit to an executor service.
Something like this untested code.
public class Main {
private static final AtomicBoolean stopRequested = new AtomicBoolean( false ) ;
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
int i = 0;
while ( ! stopRequested.get() ) {
i++;
System.out.println("i = " + i);
TimeUnit.MILLISECONDS.sleep(100); // Don’t spin too fast.
}
};
ExecutorService es = Executors.newSingleThreadedExecutorService() ;
es.submit( task ) ;
TimeUnit.SECONDS.sleep(1);
stopRequested.set( true ) ;
TimeUnit.SECONDS.sleep(1);
// Shut down here executor service. Boilerplate taken from Javadoc.
es.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!es.awaitTermination(60, TimeUnit.SECONDS)) {
es.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!es.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Executor service did not terminate");
}
} catch (InterruptedException ex) {
// (Re-)Cancel if current thread also interrupted
es.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
Like this, I have two thread. The SleepRunner thread add some random numbers to a list then change flag to true and sleep. The main thread wait SleepRunner thread until the flag in SleepRunner object change from false to true then main thread will interrupte SleepRunner thread and the program will end.
But the question is, when the while loop is no body code in main thread, the variable 'runner' is not updated inside loop in other words The program is not over after SleepRunner thread change flag from false to true. So I tried to use debug tools in idea, but the program ended smoothly. And If I write some code, like System.out.println() or Thread.sleep(1) in while loop body at main thread, the program ended successfully too. it's too incredible! Does anyone know why this happens? Thanks.
public class Test1 {
public static void main(String[] args) {
SleepRunner runner = new SleepRunner();
Thread thread = new Thread(runner);
thread.start();
while(!(runner.isFlag())){
/*try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
System.out.println("END");
thread.interrupt();
}
}
public class SleepRunner implements Runnable {
private boolean flag = false;
public boolean isFlag() {
return flag;
}
#Override
public void run() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
try {
Thread.sleep((long) (Math.random() * 200));
}
catch (InterruptedException e) {
System.out.println("Interrupted");
}
int num = (int) (Math.random() * 100);
System.out.println(Thread.currentThread().getName() + " " + num);
list.add(num);
}
flag = true;
System.out.println("30 Seconds");
try {
Thread.sleep(30000);
}
catch (InterruptedException e) {
System.out.println("Interrupted in 30 seconds");
}
System.out.println("sleep runner thread end");
}
}
You've violated the java memory model.
Here's how the JMM works*:
Each thread, whenever any field (from any object) is read or updated, flips a coin. On heads, it will make a copy and update/read from that. On tails, it won't. Your job is to ensure your code functions correctly regardless of how the coin lands, and you can't force the coinflip in a unit test. The coin need not be 'fair'. The coin's behaviour depends on the music playing in your music player, the whims of a toddler, and the phase of the moon. (In other words, any update/read may be done to a local cache copy, or not, up to the java implementation).
You may safely conclude that the only way to do it correctly, is to ensure the thread never flips that coin.
The way to accomplish that is to establish so-called 'comes before' relationships. Establishing them is done primarily by using synchronization primitives, or by calling methods that use synchronization primitives. For example, if I do this:
thread X:
synchronized(x) {
x.foo();
System.out.println(shared.y);
shared.y = 10;
}
thread Y:
synchronized(x) {
x.foo();
System.out.println(shared.y);
shared.y = 20;
}
then you've established a relationship: code block A comes before code block B, or vice versa, but you've at least established that they must run in order.
As a consequence, this will print either 0 10 or 0 20, guaranteed. Without the synchronized block, it can legally print 0 0 as well. All 3 results would be an acceptable result (the java lang spec says it's okay, and any bugs filed that you think this makes no sense would be disregarded as 'working as intended').
volatile can also be used, but volatile is quite limited.
Generally, because this cannot be adequately tested, there are only 3 ways to do threading properly in java:
'in the large': Use a webserver or other app framework that takes care of the multithreading. You don't write the psv main() method, that framework does, and all you write are 'handlers'. None of your handlers touch any shared data at all. The handlers either don't share data, or share it via a bus designed to do it right, such as a DB in serializable transaction isolation mode, or rabbitmq or some other message bus.
'in the small': Use fork/join to parallellize a giant task. The handler for the task cannot, of course, use any shared data.
read Concurrency in Practice (the book), prefer using the classes in the java.util.concurrent package, and in general be a guru about how this stuff works, because doing threading any other way is likely to result in you programming bugs which your tests probably won't catch, but will either blow up at production time, or will result in no actual multithreading (e.g. if you overzealously synchronize everything, you end up having all cores except one core just waiting around, and your code will actually run way slower than if it was just single threaded).
*) The full explanation is about a book's worth. I'm just giving you oversimplified highlights, as this is merely an SO answer.
TL; DR - is it guaranteed that by default, only one thread is ever used in any given time when observing events emitted by Observable?
It seems to me that RxJava2 is generally sequential unless expressed otherwise via things like parallel(). Even with observeOn/subscribeOn, I see that there are e.g. never two threads running simultaneously for doOnNext():
AtomicInteger counter = new AtomicInteger();
PublishSubject<Integer> testSubject = PublishSubject.create();
testSubject
.observeOn(Schedulers.io())
.doOnNext(val -> {
if(counter.incrementAndGet() > 1)
System.out.println("Whoa!!!!"); // <- never happens
Thread.sleep(20);
counter.decrementAndGet();
})
.subscribe();
for (int i = 0; i < 10000; i++) {
Thread.sleep(10);
testSubject.onNext(i);
}
No matter how I change this example - unless I go hardcore with .toFlowable(...).parallel().runOn(...), I don't see doOnNext running on different threads simultaneously.
I'd like to rely on this feature so I can ignore synchronisation issues in my operators, however I never saw it explicitly specified in the documentation for either RxJava2, RxJava1 or even just RX in general. Maybe I just missed it, could anyone pls point me to where this part of the contract is described?
Thanks!
From http://reactivex.io/documentation/contract.html
Observables must issue notifications to observers serially (not in
parallel). They may issue these notifications from different threads,
but there must be a formal happens-before relationship between the
notifications.
In your example you are not breaks this observable contract. But if you implement Observable wrong, two threads will run simultaneously:
AtomicInteger counter = new AtomicInteger();
Observable.create(emitter -> {
new Thread(() -> {
for (int i = 0; i < 10000; i++) {
try {
Thread.sleep(1);
emitter.onNext(i);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}).start();
for (int i = 0; i < 10000; i++) {
Thread.sleep(1);
emitter.onNext(i);
}
}).doOnNext(integer -> {
if (counter.incrementAndGet() > 1)
System.out.println("Whoaa!");
counter.decrementAndGet();
Thread.sleep(1);
}).subscribe();
Seems you can fix this behavior with observeOn https://github.com/ReactiveX/RxJava/issues/5550#issuecomment-325114185
remove Thread.sleep(10); to bombard the subject
Sleep for longer in the worker to simulate longer running task.
Add Thread.sleep(10000) under the loop, so that your main thread waits for the background threads to do their work
Change your thread pool .subscribeOn(Schedulers.newThread()) if you want to force each worker to run on new thread.
I have submitted a task using executors and I need it to stop after some time (e.g. 5 minutes). I have tried doing like this:
for (Future<?> fut : e.invokeAll(tasks, 300, TimeUnit.SECONDS)) {
try {
fut.get();
} catch (CancellationException ex) {
fut.cancel(true);
tasks.clear();
} catch(ExecutionException ex){
ex.printStackTrace(); //FIXME: gestita con printstack
}
}
But I always get an error: I have a shared Vector that needs to be modified by the tasks and then read by a thread, and even if I stop all the task, if the timeout occurs I get:
Exception in thread "Thread-1" java.util.ConcurrentModificationException
Is there something wrong? How can I stop the tasks submitted that are still working after 5 minutes?
Just because you call cancel() on Future doesn't mean that the task will stop automatically. You have to do some work within the task to make sure that it will stop:
Use cancel(true) so that an interrupt is sent to the task.
Handle InterruptedException. If a function in your task throws an InterruptedException, make sure you exit gracefully as soon as possible upon catching the exception.
Periodically check Thread.currentThread().isInterrupted() if the task does continuous computation.
For example:
class LongTask implements Callable<Double> {
public Double call() {
// Sleep for a while; handle InterruptedException appropriately
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
System.out.println("Exiting gracefully!");
return null;
}
// Compute for a while; check Thread.isInterrupted() periodically
double sum = 0.0;
for (long i = 0; i < 10000000; i++) {
sum += 10.0
if (Thread.currentThread().isInterrupted()) {
System.out.println("Exiting gracefully");
return null;
}
}
return sum;
}
}
Also, as other posts have mentioned: ConcurrentModificationException can be thrown even if using the thread-safe Vector class, because iterators you obtain from Vector are not thread-safe, and thus need to be synchronized. The enhanced for-loop uses iterators, so watch out:
final Vector<Double> vector = new Vector<Double>();
vector.add(1.0);
vector.add(2.0);
// Not thread safe! If another thread modifies "vector" during the loop, then
// a ConcurrentModificationException will be thrown.
for (Double num : vector) {
System.out.println(num);
}
// You can try this as a quick fix, but it might not be what you want:
synchronized (vector) { // "vector" must be final
for (Double num : vector) {
System.out.println(num);
}
}
The ConcurrentModificationException is coming from your call to tasks.clear() while your Exceutors is iterating over your tasks Vector. What you can try to do is call shutdownNow() on your ExecutorService
The most common case for ConcurrentModificationException is when the vector is being modified at the same time as it is being iterated. Often this will be done in a single thread. You need to hold a lock on the Vector for the whole iteration (and careful not to deadlock).
fut.get() is a blocking call, even after the timeout, you will block until the task is done. If you want to stop as close to the 5 minute mark as possible, you do need to check the interrupt flag, I just recommend you do so using the Thread.isInterrupted() method which preserves the interrupt state. If you want to just stop immediately and don't need to clean any state, then throw an exception which will be caught by the Future and indicated to you as an ExecutionException.
fut.cancel(true) does not do anything as the invokeAll() method has already done this for you.
Unless you use the "tasks" Collection somewhere else, you probably don't need to call clear() on it. This isn't going to be the source of your problem since the invokeAll() method is done with the List by the time you call clear(). But, if you need to start forming a list of new tasks to execute, I suggest you form a new List of tasks, not use an old List of new Tasks.
Unfortunately, I do not have an answer for your problem. I do not see enough information here to diagnose it. Nothing in the code snippet you provided indicates an improper (only unnecessary) use of library classes/methods. Perhaps if you included a full stack trace, instead of the one line error.
Put the fut.cancel(true); in the finally block
I have the following code:
public void run()
{
try
{
logger.info("Looking for new tasks to fetch... ");
// definitions ..
for(Task t: tasks)
{
logger.info(" Task " + t.getId() + " is being fetched ");
// processing ... fetching task info from db using some methods
}
Thread.sleep(FREQUENCY);
//t.start();
} catch (Exception e)
{
logger.info("FetcherThread interrupted: "+e.getMessage());
}
}
I'm trying to make the thread to sleep for a specific time "FREQUENCY" and then work again. when I execute this code in eclipse, the thread works only once and then nothing happens and process terminates. If I remove the comment from the statement: t.start(), I get "FetcherThread interrupted: null".
Can anyone tell me where I'm going wrong?
N.B.: I want the thread to be working all the time, but fetching on periods (say every 5 minutes)
You're missing any sort of loop in that code.
It seems that the thread is actually doing what you tell it to do: it runs all the tasks, then sleeps for a bit - then it has no more work to do, and so exits. There are several ways to address this, in ascending order of complexity and correctness:
The simple (and naive) way to address this is to wrap the try-catch block in an infinite loop (while(true) { ... }). This way after the thread finishes sleeping, it will loop back to the top and process all the tasks again.
However this isn't ideal, as it's basically impossible to stop the thread. A better approach is to declare a boolean field (e.g. boolean running = true;), and change the loop to while(running). This way, you have a way to make the thread terminate (e.g. expose a method that sets running to false.) See Sun's Why is Thread.stop() deprecated article for a longer explanation of this.
And taking a step further back, you may be trying to do this at too low a level. Sleeping and scheduling isn't really part of the job of your Runnable. The actual solution I would adopt is to strip out the sleeping, so that you have a Runnable implementation that processes all the tasks and then terminates. Then I would create a ScheduledExecutorService, and submit the "vanilla" runnable to the executor - this way it's the job of the executor to run the task periodically.
The last solution is ideal from an engineering perspective. You have a class that simply runs the job once and exits - this can be used in other contexts whenever you want to run the job, and composes very well. You have an executor service whose job is the scheduling of arbitrary tasks - again, you can pass different types of Runnable or Callable to this in future, and it will do the scheduling bit just as well. And possibly the best part of all, is that you don't have to write any of the scheduling stuff yourself, but can use a class in the standard library which specifically does this all for you (and hence is likely to have the majority of bugs already ironed out, unlike home-grown concurrency code).
Task scheduling has first-class support in Java, don't reinvent it. In fact, there are two implementations: Timer (old-school) and ScheduledExecutorService (new). Read up on them and design your app aroud them.
Try executing the task on a different thread.
You need some kind of loop to repeat your workflow. How shall the control flow get back to the fetching part?
You can put the code inside a loop.( May be while)
while(condition) // you can make it while(true) if you want it to run infinitely.
{
for(Task t: tasks)
{
logger.info(" Task " + t.getId() + " is being fetched ");
// processing ... fetching task info from db using some methods
}
Thread.sleep(FREQUENCY);
}
Whats happening in your case its running the Task loop then sleeping for some time and exiting the thread.
Put the thread in a loop as others have mentioned here.
I would like to add that calling Thread.start more than once is illegal and that is why you get an exception.
If you would like to spawn multiple thread create one Thread object per thread you want to start.
See http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#start()
public void run()
{
while (keepRunning) {
try
{
logger.info("Looking for new tasks to fetch... ");
// definitions ..
for(Task t: tasks)
{
logger.info(" Task " + t.getId() + " is being fetched ");
// processing ... fetching task info from db using some methods
t.start();
}
Thread.sleep(FREQUENCY);
} catch (Exception e) {
keepRunning = false;
logger.info("FetcherThread interrupted: "+e.getMessage());
}
}
}
Add a member call keepRunning to your main thread and implement an accessor method for setting it to false (from wherever you need to stop the thread from executing the tasks)
You need to put the sleep in an infinite loop (or withing some condition specifying uptill when you want to sleep). As of now the sleep method is invoked at the end of the run method and behavior you observe is correct.
The following demo code will print "Sleep" on the console after sleeping for a second. Hope it helps.
import java.util.concurrent.TimeUnit;
public class Test implements Runnable {
/**
* #param args
*/
public static void main(String[] args) {
Test t = new Test();
Thread thread = new Thread(t);
thread.start();
}
public void run() {
try {
// logger.info("Looking for new tasks to fetch... ");
// definitions ..
// for(Task t: tasks)
// {
// logger.info(" Task " + t.getId() + " is being fetched ");
// // processing ... fetching task info from db using some methods
// }
while (true) { // your condition here
TimeUnit.SECONDS.sleep(1);
System.out.println("Sleep");
}
// t.start();
} catch (Exception e) {
// logger.info("FetcherThread interrupted: "+e.getMessage());
}
}
}
You could try ScheduledExecutorService (Javadoc).
And us it's scheduleAtFixedRate, which:
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.