Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm studying Java using the book by Gosling. There is a question in the chapter devoted to the multithread programming:
Write a program, which will create a message each second from the beginning of the session. Another thread of this program should create a message each 15 sec. You should provide the possibility of every second-notification by the thread which is counting time.
Here is my solution (it doesn't work and i can't understand why, i think, i just can't properly understand the principle on creating a thread):
public class test {
public static void main (String [] args) throws InterruptedException{
chrono my=new chrono();
my.timer();
Runnable t1=new messenger(5);
Runnable t2=new messenger(1);
new Thread(t1, "t1").start();
new Thread(t2, "t2").start();
}
}
class chrono {
static int time=0;
public synchronized void timer() throws InterruptedException {
Thread.sleep(1000);
time++;
System.out.println(time);
notifyAll();
}
}
class messenger implements Runnable {
int time;
messenger(int time) {
this.time=time;
}
synchronized void timerListener() {
try {
while (chrono.time%time!=0) {
wait();
}
System.out.println("Thread "+this.time);
} catch(InterruptedException e) {}
}
public void run() {
timerListener();
}
}
New version:
public class test {
public static void main (String [] args) throws InterruptedException{
Chronometr my=new Chronometr();
Runnable t1=new Messenger(5, my);
new Thread(t1, "t1").start();
for (int i=0;i<6;i++) {
synchronized(my) {
my.timeCount();
my.notifyAll();
}
}
}
}
class Chronometr {
static int time=0;
public void timeCount() throws InterruptedException {
Thread.sleep(1000);
time++;
System.out.println(time);
}
}
class Messenger implements Runnable{
int time;
public Chronometr ch;
Messenger(int time, Chronometr ch) {
this.time=time;
this.ch=ch;
}
public void waitForTime() {
synchronized (ch) {
try{
while (Chronometr.time%time!=0)
ch.wait();
System.out.println("Thread "+this.time);
}
catch(InterruptedException e) {}
}
}
public void run() {
waitForTime();
}
}
Last change:
public class test {
public static void main (String [] args) throws InterruptedException{
Chronometr my=new Chronometr();
Runnable t1=new Messenger(5, my);
new Thread(t1, "t1").start();
for (int i=0;i<10;i++) {
synchronized(my) {
Chronometr.time+=1;
System.out.println(Chronometr.time);
my.notifyAll();
//my.wait();
}
Thread.sleep(1000);
}
}
}
Edit: Just noticed another big problem: The code calls Thread.sleep() inside a synchronized block. No! No! No! No! No!
When I run the newer version of your program as-is, the Messenger thread usually never gets to run: Here's what I think happens:
main thread messenger thread
----------- ----------------
starts messenger
locks chronometer
sleeps enters waitForTime()
blocks trying to lock
chronometer
---one second later---
wakes up from sleep
increments time
prints message
calls notifyAll()
(Has no effect, 'cause
messenger is not in
wait() call)
ulocks the lock
re-locks the lock wakes up
sleeps blocks trying to lock
chronometer
. .
. .
. .
Try moving the Thread.sleep(1000) call out of the Chronometer.timeCount() method, into the main() method, outside of the synchronized(my) block. I'm guessing that the output will be more like what you expected.
Original answer below the line,
Your biggest problem is this:
chrono.timer() method calls notifyAll() on itself (i.e., on the chrono instance referenced by the "my" variable in main()). Who calls wait() on that object? Nobody is who. Your messanger objects wait() on themselves. Who notifies them? Nobody is who.
Other comments (in no particular order):
(1) Class names should be CamelCase beginning with a capital letter. The more your code looks like everybody else's, the more everybody else will be willing to try to understand it and help you out.
(2) If you have only one variable of type FooBarBaz, then the variable should be named fooBarBaz. Same reason.
(3) Class names should be nouns (e.g., Chronometer instead of the ambiguous chrono), method names should be verbs (e.g., waitForTimerTick() instead of timerListener()). Same reason.
(4) the my.timer(); call in main could not have any possible effect on the threads that you create and start after it returns. A foo.notify() call does nothing if there are no other threads already waiting in foo.wait() when notify() is called.
(4a) A variable named "my" is an abomination.
(5) the my.timer() call waits for one second, increments my.time, notifies nobody, and then it's done. For good. In particular, nobody will ever increment my.time again.
(5a) The problem statement clearly says that the program should go on forever periodically printing out messages, but there are no loops in your program except for the wait() loop in messenger.timerListener().
(6) You might want to get some more experience writing single-threaded programs that solve real problems before you try to tackle threads.
Related
I am not very good at multithreading and am baffled by this code:
public class Main {
public static void main(String... args) throws Exception {
new Thread(Main::test).start();
}
private static synchronized void test() {
new Thread(Main::test).start();
System.out.println("TEST");
}
}
Can it result in a deadlock or not? If so, then why have I not been able to get it to deadlock? My thinking is, thread 1 acquires lock on test(), then another thread, created in test() tries to acquire it and they should be waiting on each other. But they aren't, why not?
I know, that adding join() in test() will make it result in a deadlock, but how come the example below doesn't use joins and deadlocks?
This code results in a deadlock literally every time I run it:
public class Main {
public static void main(String... args) {
new Thread(Main::test).start();
new Thread(Main::test2).start();
}
private static void test() {
synchronized (Integer.class) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
synchronized (Float.class) {
System.out.println("Acquired float");
}
}
}
private static void test2() {
synchronized (Float.class) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
synchronized (Integer.class) {
System.out.println("Acquired integer");
}
}
}
}
No, the code in the first example cannot deadlock. The newly started threads will simply wait until the previous thread exits the method to acquire the lock.
The code in the second example deadlocks because the locks are acquired in opposite order and because of the sleeps are reliably going to block each other.
When you're at the phase where you're first learning how to think about concurrency and related problems, I would very much recommend using physical props to keep your thoughts and hypotheses clear and explicit.
For example, grab a A3 sheet of paper, set up a "race track" where you use something like Monopoly pieces to signify what you're doing in your code, what you expect to happen, and what your experiments show actually happens.
When your experiments don't work out, take a small piece of the beginning first, and verify it. Then add some more, and so on.
It helps if you read about how actual computers (not the CS ideal or conceptual computers) currently work. How the CPU gets data out of the main memory into its cache. How two or three CPUs decide which one of them can handle data in one cache line at a time. Then, how the Java Memory Model needs you to write your source code so that the JVM knows what you actually mean to happen.
This code end up with different results if I change the parameter of sleep(), and here is some sample outcomes:
1.sleep(1l), the thread will always terminate automaticlly, the "Stoped" statement will always be printed, and the icon of "Terminate" in Eclipse will be grey too. (seems working perfectly huh?)
2.sleep(1000l), here comes the problem, if main thread sleeps for 1 second, the Thread v will never terminated automaticlly, the "Stoped" will not be printed, and the icon of "Terminate" is red, which means there is still some thread running.
I know it could be solved if I add "volitale" for the parameter "isRunning", but I wonder why and how does the sleep() statement affect the outcome?
PS:I'm a newbie for both java and english, so I apologize for any possible discomforts due to this question.
public class VolitaleTest {
public static void main(String[] args) throws InterruptedException {
Vo v = new Vo();
new Thread(v).start();
Thread.sleep(1000l);
v.setRunning(false);
System.out.println(v.i);
}
}
class Vo implements Runnable {
private boolean isRunning = true;
int i = 0;
public void run() {
while (isRunning) {
i++;
// System.out.println("Running");
/*
* Once you add this statement, you will always be able to terminate
* the program automatically, no matter how long the thread sleeps.
*/
}
System.out.println("Stoped.");
}
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
}
volatile makes it possible for what one thread wrote up to and including writing to the volatile variable to be visible to another thread starting from when it reads that variable. If the variable is not volatile then that happens-before memory relationship is not guaranteed.
I was going to use threads for each sound in a game engine I'm making. The problem is, whenever I make a new thread that has a while(true) statement, the other thread stops running.
I made a class to test this, and it only prints "goodbye", not "hello". I was wondering how to make the two threads run at the same time.
public class testor {
public static void main(String args[]){
testor test=new testor();
test.runTest();
}
class threadTest implements Runnable{
#Override
public void run() {
while(true){
System.out.println("goodbye");
}
}
}
public void runTest(){
threadTest test=new threadTest();
test.run();
while(true){
System.out.println("hello");
}
}
}
Since you are doing test.run(); you are only calling the method of that class but not starting the thread.
So in order to answer your question: there is no such a thread stopping the other thread from running? because you have only one Thread that is looping for ever and printing the message System.out.println("goodbye");
If that method is not looping for ever, it would return to the runTest method and then you would see the System.out.println("hello");
Summary:
For starting a Thread use the Thread::start method and not the run.
Using (new ThreadTest()).run() does not start a new Thread, but just invokes the run() method in the current thread.
To run the code in a separate thread do:
(new Thread(new ThreadTest())).start();
That's because you're not creating a new thread. Just naming a class something containing "thread" will not make it a thread, and a Runnable is no thread - it's a class like any other, with no special semantics or behaviour.
It's only special in that you can pass it to a Thread for execution.
public class Testor {
public static void main(String args[]){
Testor test=new Testor();
test.runTest();
}
class MyRunnable implements Runnable{
#Override
public void run() {
while(true){
System.out.println("goodbye");
}
}
}
public void runTest(){
Thread testThread = new Thread(new MyRunnable());
testThread.start();
while(true){
System.out.println("hello");
}
}
}
You should probably also adhere to the Java coding standards regarding your class and variable names if you do not want your code to look like an alien when combined with most other existing Java code.
Additionally, multithreading is more than just being able to start a new thread. You should also read about synchronisation issues - it's more complicated to do correctly than you might imagine.
Your run method contains an infinite loop.
The runTest() method creates the thread which means you'll have 2 execution stacks the main stack, and the runnable threadTest stack.
since you're running the thread method first that contains an infinite loop, you'll always get the output "good Bye".
Remove the infinite loop from run() method.
This code is from Effective Java (Item 66): (without sync or volatile this never ends)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
As Bloch mentioned in that chapter it will never write "finished" to the console. I've been playing around with this class, and add that line to the runnable run method:
System.out.println("im still running");
With this the while loop doesn't only increment i but prints out this string in every loop. But what drives me crazy, that this way the thread stops after 1 sec, when main thread comes back from sleep.
modified: (stops without volatile/sync)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;System.out.println("im still running");}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
So what is the logic behind this?
Precisely, it is just not guaranteed that the thread will ever stop, but it is not forbidden that it does stop. The logic behind this is provided by the Java Memory Model, which is a rather complicated topic, but needed in order to understand Multithreading in Java.
The concept is that a write to a non-volatile field of one thread is only required to be seen by another thread if these two actions synchronize with each other. A compiler is allow to reorder some actions if the behavior exhibited by the thread it is executed in does not change. But another thread might see this. So you need proper synchronization in order to tell the compiler that reordering is not allowed in some parts.
Read the full paper about this here: JSR-133
Writing data to the console is often implemented a thread safe operation.
In that case your act of writing data to the console can also trigger updating of the canrunstatic variable as seen by your backgroundThread.
Note that this is not promised by the Java Memory Model, nor by the implementation of java System.out
This question already has answers here:
Please explain the output from Thread run() and start() methods
(4 answers)
Closed 8 years ago.
I was working on Threads when a question struck to my mind..If we can directly call run() method with the object of a class like any ordinary method then why do we need to call Thread.start() to call run() method..I tried both the methods as shown and got same result with both of them
First attempt by calling run() method directly
class Abc extends Thread
{
public void run()
{
for(int i=0;i<5;i++)
{
System.out.println("Abc");
}
try
{
Thread.sleep(100);
}catch(Exception e)
{
System.out.println("Error : "+ e);
}
}
}
class Xyz extends Thread
{
public void run()
{
try
{
for(int i=0;i<5;i++)
{
System.out.println("Xyz");
}
Thread.sleep(100);
}catch(Exception e)
{
System.out.println("Error : "+ e);
}
}
}
public class ThreadDemo
{
public static void main(String[] args)
{
Abc ob=new Abc();
Xyz oc=new Xyz();
ob.run();
oc.run();
}
}
Second attempt by calling Thread.start()
public class ThreadDemo
{
public static void main(String[] args)
{
Abc ob=new Abc();
Xyz oc=new Xyz();
Thread t1,t2;
t1=new Thread(ob);
t2=new Thread(oc);
t1.start();
t2.start();
}
}
If you call run() directly, the code gets executed in the calling thread. By calling start(), a new Thread is created and executed in parallel.
If you directly call run(), then all the work will be done on the main thread.
By using Thread.start, then it will executed on a new thread other than the main thread ;)
To observe what the difference is, increase your sleep calls to something longer like 10 seconds. This will make it obvious that you need Thread.start to avoid the first task waiting on the second.
In the case where you use Thread.start, you will see that output of both threads appears immediately.
In the case where you use run, you will see that the output of the first appears, then a 10 second delay, then the output of the second.
If you call run() method directly then code will run inline. To run the code in separate thread it is necessary to call Thread.start().
When you call start() method on thread reference it create span entirely context area. Then thread will have independent stack from where you are calling. More over start() invokes OS native thread to start it in separate memory context.
While run() method invocation considered as simple method call, and you won't have benefit of concurrency as its executing is current stack.