My program has a thr () function that returns a string value, but before returning, the value is overridden in Thread, but when called in main (), this function will return the string that was before being processed in Thread. If you add Sleep, everything will be fine before, but I think this is not a good solution to the problem. If there are suggestions on how to solve this problem, then it would be bad.
Code:
fun main() {
println(thr())
}
fun thr(): String {
var x = "Before thread"
Thread {
x = "After thread"
}.start()
// Thread.sleep(100)
return x
}
The desired result is - "After thread"
The current result - "Before thread"
You have a race condition, because the value of x at the return statement depends on whether your created thread has run and executed that line yet - Thread.sleep just makes the current thread (the one that's executing thr(), not the one you're creating) wait so the new one has a chance to finish.
There's also the issue that the value of x that Thread 1 sees might not be what Thread 2 sees, so it won't see the updated value at the point where it's returning it. This is down to some under-the-hood memory trickery that improves performance, and it's why you need to handle synchronization.
Basically you need to read up on concurrency and the different ways it can be handled. This is for Java but it's the basics of what's going on with threading in Kotlin too:
https://docs.oracle.com/javase/tutorial/essential/concurrency/
You need to be aware of this stuff in general, so it's worth getting your head around it!
I guess what you want to do is to wait for the thread to finish and then return x. In this case, you can use the join method:
fun thr(): String {
var x = "Before thread"
val t = Thread {
x = "After thread"
}
t.start()
t.join()
return x
}
Related
When I try to use methods inside a class in which I extend Thread it does not receive the methods after the run.
My class:
public class PassPhraseValidator<E> extends Thread {
private List<E> list;
private boolean isValid;
private String passPhrase;
public PassPhraseValidator(List<E> list) {
this.list = list;
}
public String getPassPhrase() {
return passPhrase;
}
public boolean isValid() {
return isValid;
}
public void run(){
this.passPhrase = Arrays.toString(list.toArray());
this.isValid = list.stream().filter(e -> Collections.frequency(list, e) > 1).count() == 0;
}
}
So when I execute this class like this:
PassPhraseValidator<Integer> validIntegerPassPhrase = new PassPhraseValidator<>(Arrays.asList(12, 18, 15, 32));
validIntegerPassPhrase.start();
System.out.println(validIntegerPassPhrase.getPassPhrase() + " valid: " + validIntegerPassPhrase.isValid());
It gives me false while it should be true because the run function wasn't ran yet.
What am I doing wrong here? How can I make multithreading part of this? It does work when I directly put it inside the methods.
The last System.out.println statement does not wait for your thread (the run function) to complete.
One way to wait for its completion is to call the join method
validIntegerPassPhrase.join(); //Need to handle the InterruptedException it might throw
System.out.println(validIntegerPassPhrase.getPassPhrase() + " valid: " + validIntegerPassPhrase.isValid());
Explanation
What you are doing is called multithreading. This allows multiple threads to execute code concurrency or in parallel. Programs run on something called the main thread. This means one thread is executing all code systematically; one instruction after another. When introducing another thread like you are, the program execution is being done on different logic at the same time. So, when you execute the start() method on your implementation of the thread class, you are causing it to execute it's respective run() method in the background until; it completes, an exception is thrown, the application is shutdown, or the thread is stopped.
Lets step through your code and analyze the scenario.
Thread object is instantiated by the main thread. Lets call this new thread thread2.
thread2 is started by the main thread.
thread2 and the main thread are both running in parallel. This means code is being executed by both of them (for simplicity) at the same time.
Two possibilities could be occurring for this issue; Java Memory Barrier (beyond the scope of this question but more reference here) or timing. The main thread is most likely reading the print statement before thread2 can finish it's respective run() method.
Solution
An approach may be not to use multi-threading at all. The creation of threads is quite a costly operation and should not be done frequently. Typically, in app's that require multi-threading thread-pools are utilized instead.
Utilize the join() blocking function. Join forces the calling thread (in this case it would be the main thread) to wait for the respective thread to finish execution before continuation.
Implement the thread with use of Promise. This object is a wrapper for the Future class, allowing for the get() method to be blocking. This means the calling thread (in this case it would be the main thread) to wait for the respective thread to finish execution before continuation. An example of Promise's can be found here.
Given that I have the following test-code:
import java.util.concurrent._
object TestTime {
def main(args: Array[String]) {
println("starting....")
val service = Executors.newSingleThreadExecutor
val r = new Callable[Unit]() {
override def call(): Unit = {
//your task
val t0 = System.nanoTime
val total = sum(1000000000)
val t1 = System.nanoTime
println("Elapsed time " + (t1 - t0) / 1e9 + " secs")
println(s"total = $total")
}
}
val f = service.submit(r)
try {
// attempt the task for 2 second
f.get(2, TimeUnit.SECONDS)
} catch {
case _: TimeoutException =>
f.cancel(true)
println(s"Timeout....")
} finally {
service.shutdown()
}
println("after 2 seconds....")
for(i <- 1 to 2){
println(s"$i ...")
Thread.sleep(1000)
}
println("main thread ends...")
}
//Given that sum() is written by others and I cannot change it.
def sum(k: Int): BigInt = {
var total: BigInt = 0
for (i <- 1 to k) {
total += i
}
total
}
}
I would like to execute the sum at most 2 seconds. If it exceeds the time limit, the corresponding thread should be interrupted immediately. To interrupt that thread, I have tried two methods when catch TimeoutException:
f.cancel(true)
service.shutdownNow()
However, according to my test, the above methods cannot interrupt the thread.
So I would like to know is there method to interrupt a thread compulsively.
According to JavaDocs for both Future#cancel and ExecutorService#shutdownNow, the typical implementation is that these methods result in interrupting the underlying thread.
If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
Note particuarly the last comment. Thread interruption via the Thread#interrupt method is a cooperative process. When one thread interrupts another, it results in setting the target thread's interrupted status. Also, if the target thread is blocked in certain specific methods, then that thread will experience an InterruptedException.
If the code executing in the target thread neither checks for interrupted status periodically via the Thread#isInterrupted method nor calls a blocking method and handles InterruptedException, then interruption effectively does nothing. That code is not cooperating in the interruption process, so there is effectively no way to shut it down, despite thread interruption.
//Given that sum() is written by others and I cannot change it.
Ideally, long-running code intended for execution in background threads would be changed to cooperate in the thread interruption. In your example, a viable technique would be to change sum to check Thread#isInterrupted every N iterations of the for loop, and if interrupted, abort the loop. Then, it could either throw an exception to indicate that it didn't complete or possibly return some sentinel BigInt value to indicate the abort if that's appropriate.
If the invoked code truly cannot be changed, then you cannot halt it by thread interruption. You could potentially use daemon threads so that at least these threads won't block JVM exit during shutdown.
Following piece is from a JUnit testcase that tests 4 different implementations of Sorter. It invokes the only method Sorter has viz sort().
I want to kill the sorting process if it takes longer than say 2 seconds (Because I don't care for any implementation that takes longer than 2 seconds to sort() say 500000 Integers).
I'm new the Java multi-threading and after looking at all other threads ( How to kill a java thread? and a few others) on SO, I figured following as solution to my problem. Question is, would it work consistently, or could there be any issues? I don't care abt the array or it's contents as reset() would reset it's contents.
Reason why I call it uncooperative is because s.sort() is out of my control.
protected E[] arr;
#Test
public void testSortTArray() {
boolean allOk = true;
for (Sorter s : TestParams.getSorters()) {
System.out.println("Testing: " + s.getName() + " with " + arrayLenToTestWith + " elems of type "
+ classOfElemType.getName());
reset();
long startTime = System.nanoTime();
MyThread test = new MyThread(s, arr);
test.start();
try {
test.join(TestParams.getTimeThreshold());
} catch (InterruptedException e) {
e.printStackTrace();
}
if (test.isAlive())
test.interrupt();
if (!test.isInterrupted()) {
System.out.println("Time taken: " + ((System.nanoTime() - startTime) / (1000000)) + "ms");
if (!isSorted(arr)) {
allOk = false;
System.err.println(s.getName() + " didn't sort array.");
}
} else {
allOk = false;
System.err.println(s.getName() + " took longer than .");
}
}
assertTrue("At least one algo didn't sort the array.", allOk);
}
public class MyThread extends Thread {
private Sorter s;
private E[] arr;
public MyThread(Sorter s, E[] arr) {
this.s = s;
this.arr = arr;
}
#Override
public void run() {
s.sort(arr);
}
}
--- edit: answer ---
Based on comments from everyone:
No. What I'm doing is not safe as Thread.interrupt() will not suspend the thread, it'll just set it's interrupted state, which if not checked by the thread's run() implementation, is useless.
In this case the next Sorter's sort() would be called on the same array (which is still being sorted by the old "interrupted" thread), thus making things unsafe.
One option is to create a separate Process instead of a Thread. A Process can be killed.
Obviously the parameter passing isn't easy in this case as it involves some IPC.
As you may have seen from the other questions you mention, it isn't possible to reliably stop a Java thread without its cooperation, because interrupt() ony works if the thread tests for it (deliberately or inadvertently).
However, it is possible to kill a process. If you spawn each sorting algorithm in a separate process, then you can kill it forcibly.
The downside is that interacting with the process is significantly harder than interacting with a thread, since you don't have shared variables.
Without a thread's cooperation, there is no reliable and safe way to stop it. With a thread's cooperation, you can interrupt or stop a thread using the mechanism it supports. Threads just don't provide this kind of isolation ... you have to use multiple processes.
This may be a case for Thread.stop(). Do read the disclaimer in the javadoc, though, in particular:
Deprecated. 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.
would it work consistently, or could there be any issues?
It would work except that you need to handle the thread interrupt correctly. thread.interrupt() will only work if the sort method supports it. I suspect that the method will not be calling Thread.sleep(), wait(), or other such methods. Therefore it needs to test to see if it has been interrupted as it does its processing:
while (!Thread.currentThread().isInterrupted()) {
// do sort stuff
}
If it doesn't do that then interrupting the thread will not stop the processing. I would certainly add another test.join(); after the interrupt to make sure that the thread finishes before you start another sort operation.
I have a loop that doing this:
WorkTask wt = new WorkTask();
wt.count = count;
Thread a = new Thread(wt);
a.start();
When the workTask is run, the count will wt++ ,
but the WorkTask doesn't seems change the count number, and between the thread, the variable can't share within two thread, what did I wrote wrong? Thanks.
Without seeing the code for WorkThread it's hard to pin down the problem, but most likely you are missing synchronization between the two threads.
Whenever you start a thread, there are no guarantees on whether the original thread or the newly created thread runs first, or how they are scheduled. The JVM/operating system could choose to run the original thread to completion and then start running the newly created thread, run the newly created thread to completion and then switch back to the original thread, or anything in between.
In order to control how the threads run, you have to synchronize them explicitly. There are several ways to control the interaction between threads - certainly too much to describe in a single answer. I would recommend the concurrency trail of the Java tutorials for a broad overview, but in your specific case the synchronization mechanisms to get you started will probably be Thread.join and the synchronized keyword (one specific use of this keyword is described in the Java tutorials).
Make the count variable static (it looks like each thread has its own version of the variable right now) and use a mutex to make it thread safe (ie use the synchronized instruction)
From your description I came up with the following to demonstrate what I perceived as your issue. This code, should output 42. But it outputs 41.
public class Test {
static class WorkTask implements Runnable {
static int count;
#Override
public void run() {
count++;
}
}
public static void main(String... args) throws Exception {
WorkTask wt = new WorkTask();
wt.count = 41;
Thread a = new Thread(wt);
a.start();
System.out.println(wt.count);
}
}
The problem is due to the print statement running before thread had a chance to start.
To cause the current thread ( the thread that is going to read variable count ) to wait until the thread finishes, add the following after starting thre thread.
a.join();
If you are wishing to get a result back from a thread, I would recommend you to use Callable
interface and an ExecutorSercive to submit it. e.g:
Future future = Executors.newCachedThreadPool().submit
(new Callable<Interger>()
{
int count = 1000;
#Override public Integer call() throws Exception
{
//here goes the operations you want to be executed concurrently.
return count + 1; //Or whatever the result is.
}
}
//Here goes the operations you need before the other thread is done.
System.out.println(future.get()); //Here you will retrieve the result from
//the other thread. if the result is not ready yet, the main thread
//(current thread) will wait for it to finish.
this way you don't have to deal with the synchronization problems and etc.
you can see further about this in Java documentations:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html
I am using a third-party library to process a large number of data sets. The process very occasionally goes into an infinite loop (or is blocked - don't know why and can't get into the code). I'd like to kill this after a set time and continue to the next case. A simple example is:
for (Object data : dataList) {
Object result = TheirLibrary.processData(data);
store(result);
}
processData normally takes 1 second max. I'd like to set a timer which kills processData() after , say, 10 seconds
EDIT
I would appreciate a code snippet (I am not practiced in using Threads). The Executor approach looks useful but I don't quite know how to start. Also the pseudocode for the more conventional approach is too general for me to code.
#Steven Schlansker - suggests that unless the thirdparty app anticipates the interrupt it won't work. Again detail and examples would be appreciated
EDIT
I got the precise solution I was wanting from my colleagues Sam Adams, which I am appending as an answer. It has more detail than the other answers, but I will give them both a vote. I'll mark Sam's as the approved answer
One of the ExecutorService.invokeAll(...) methods takes a timeout argument. Create a single Callable that calls the library, and wrap it in a List as an argument to that method. The Future returned indicate how it went.
(Note: untested by me)
Put the call to the library in another thread and kill this thread after a timeout. That way you could also proces multiple objects at the same time if they are not dependant to each other.
EDIT: Democode request
This is pseudo code so you have to improve and extend it. Also error checking weather a call was succesful or not will be of help.
for (Object data : dataList) {
Thread t = new LibThread(data);
// store the thread somewhere with an id
// tid and starting time tstart
// threads
t.start();
}
while(!all threads finished)
{
for (Thread t : threads)
{
// get start time of thread
// and check the timeout
if (runtime > timeout)
{
t.stop();
}
}
}
class LibThread extends Thread {
Object data;
public TextThread(Object data)
{
this.data = data;
}
public void processData()
{
Object result = TheirLibrary.processData(data);
store(result);
}
}
Sam Adams sent me the following answer, which is my accepted one
Thread thread = new Thread(myRunnableCode);
thread.start();
thread.join(timeoutMs);
if (thread.isAlive()) {
thread.interrupt();
}
and myRunnableCode regularly checks Thread.isInterrupted(), and exits cleanly if this returns true.
Alternatively you can do:
Thread thread = new Thread(myRunnableCode);
thread.start();
thread.join(timeoutMs);
if (thread.isAlive()) {
thread.stop();
}
But this method has been deprecated since it is DANGEROUS.
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#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."
I've implemented the second and it does what I want at present.