Hy, i try to follow this http://www.studytonight.com/java/synchronization.php
here's my code
class First {
public void display(String msg)
{
System.out.print("["+msg);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
System.out.println("]");
}
}
class Second extends Thread{
String msg;
First fobj;
Second(First fp,String str){
msg=str;
fobj=fp;
start();
}
public void run(){
synchronized(fobj){
fobj.display(msg);
}
}
}
public class Main {
public static void main(String[] args) {
// TODO code application logic here
First f=new First();
Second s1=new Second(f,"welcome");
Second s2=new Second(f,"new");
Second s3=new Second(f,"programmer");
}
}
and here's my result
run:
[welcome]
[programmer]
[new]
BUILD SUCCESSFUL (total time: 3 seconds)
what's wrong with my code? why the result isn't welcome new programmer ?
All the threads start almost at the same time, and compete with each other to get the lock on the shared object.
There is no guarantee that the second thread asks for the lock before the third one. And even if that is the case, the lock is not fair, so there is no guarantee that the first thread waiting for the lock will get it first.
The only guarantee you can have with the above code is that only one of the thread will be able to execute the synchronized method at a time.
Related
According to the information I've got so far, I've understood that Thread.sleep() pauses the thread where the method is called. For example, if I call it within the main method it pauses the execution of main. if I call it inside the run of a certain thread, it would only pause that thread.
I need an expertise to confirm my understanding as I feel lost among the too much information on web.
I've been practicing to apply this, throw the following:
a Thread class, Player1:
public class Player1 extends Thread{
public void run()
{
try {
System.out.println("I'm going to sleep");
Thread.sleep(2000);
System.out.println("I'm awake");
} catch (InterruptedException ex) {
}
}
}
a Thread class, Client:
public class Clients extends Thread {
public void run()
{
printer2(10);
}
public synchronized static void printer2(int val)
{
System.out.println(val);
System.out.println(val);
System.out.println(val);
System.out.println(val);
System.out.println(val);
System.out.println(val);
}
}
they're called inside main method:
public static void main(String[] args) throws InterruptedException {
Clients c1 = new Clients(10);
Player1 p = new Player1();
p.start();
c1.start();
}
What happens (according to my understanding): the sleep is applied only to the execution of the player1 thread not to the main thread or the client thread.
Similarly, if I add a sleep method in the run of the Clients thread, it would sleep independently of the other Thread. for instance: this sleeps for its own 1 second and this sleeps for its 1 second as well (even if those 2 1 seconds overlap)
Correct me if I'm wrong please
Thanks in advance!
I don't know how to make for a thread to run until the task is finished.
So i have this class:
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
System.out.println(3);
//here the next code to run
}
}
And another that try for example to add data in database:
public class ThreadRunnable implements Runnable{
public void run(){
//code to make the thread waits until the insert is done
//code for inserting data in database
}
}
So, inside method run() i want something like:
- try to insert data in database
- if connection to database is down, wait 5 seconds and try again
- if connection is ok, then insert data, and return successful message that data is added
Is this possible, and if yes, how?
Thanks!
You don’t need to wait for a thread. Just do the retries in a loop in your Runnable:
public void run() {
try {
while (true) {
try {
// Do database operations here
// Succeeded
break;
} catch (SQLException e) {
// Failed; log exception and try again.
logger.log(Level.INFO, "Couldn't save data.", e);
}
// Wait before trying again.
Thread.sleep(5000);
}
} catch (InterruptedException e) {
logger.log(Level.INFO, "Interrupted; exiting.", e);
}
}
Note: An interrupt is an explicit request for a thread to stop what it’s doing and self-terminate. The InterruptedException should not be caught inside the loop, because you want the loop to terminate in the event of an interrupt.
On the other hand, you do want the loop to keep executing in the event of an SQLException, so it should be caught inside the loop.
You can do something like that :
1) Add a waitFor function in your ThreadRunnable
2) Add synchronization via un LOCK variable
The code :
public class ThreadRunnable implements Runnable{
private boolean ended=false;
private final Object LOCK=new Object();
public void run(){
// do my stuff...
...
//at the end, notify the thread waiting for : it will wake up
synchronized(LOCK)
{
ended=true;
LOCK.notifyAll();
}
}
/**
Waits until the task is done
*/
public void waitFor()
{
synchronized(LOCK)
{
while(!ended)
{
//sleeps until notifAll is called (see run())
wait();
}
}
}
}
(in this code, you have to add the try/catch for the InterruptedException)
In your main :
public class MainTest {
public static void main(String[] args){
ThreadRunnable t1 = new ThreadRunnable();
Thread t2 = new Thread(t1);
t2.start();
t1.waitFor();
System.out.println(3);
//here the next code to run
}
}
I have a simple question about managing Threads. I have 3 process that share the same Semaphore with one permit. in normal situation, the first process takes this permit and release two permit tho the second process. The second process release 3 permits to the third process. I given an example to illustrate my problem.
First one:
public class Process0 extends Thread{
Semaphore s;
public Process0(Semaphore s){
this.s = s;
}
public void run(){
try {
sleep(20000);
s.acquire();
System.out.println("hello");
} catch (InterruptedException ex) {
Logger.getLogger(Process.class.getName()).log(Level.SEVERE, null, ex);
}
s.release(2);
}
}
Second Process:
public class Process1 extends Thread{
Semaphore s;
public Process1(Semaphore s){
this.s = s;
}
public void run(){
try {
this.sleep(10000);
s.acquire(2);
System.out.println("Hello 2");
} catch (InterruptedException ex) {
Logger.getLogger(Process1.class.getName()).log(Level.SEVERE, null, ex);
}
s.release(3);
}
}
And last one:
public class Process2 extends Thread{
Semaphore s;
public Process2(Semaphore s){
this.s = s;
}
public void run(){
try {
System.out.println("Acquire process 3 ");
s.acquire(3);
System.out.println("Hello 3");
} catch (InterruptedException ex) {
Logger.getLogger(Process2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
The problem is. When i run this three process and be sure that process 3 is the first that excute the acquire. I will have a deadlock. Process 2 never print "Hello 3" and process 1 never print "Hello 2".Why ?
Semaphore s = new Semaphore(1);
Process0 p = new Process0(s);
Process1 p1 = new Process1(s);
Process2 p2 = new Process2(s);
p.start();
p1.start();
p2.start();
Your Semaphore is constructed as new Semaphore(1), which only has one permit available to be acquired. The call s.acquire(3) will never return since the semaphore will never have three permits available. The attempt to acquire a single permit by Process also blocks since acquisitions are ordered and Process2 arrived "first":
The release method javadoc states that an acquisition can happen when
Some other thread invokes the release() method for this semaphore and the current thread is next to be assigned a permit.
This minimal, single-thread example will show you:
Semaphore s = new Semaphore(1);
s.acquire(2);
System.out.println("Didn't deadlock!");
The solution to this is to use Semaphore.acquire() which requests one permit, or Semaphore.acquire(1) which also requests only one permit.
You also need to make sure that you acquire and release the same amount of permits, unless you have a very good reason to misuse Semaphore. From Javadoc:
There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire [or that a thread releases all of its permits]. Correct usage of a semaphore is established by programming convention in the application.
Additionally, it seems that you might be using the wrong synchronizer for this task. You could use a CyclicBarrier or other class usable for synchronization.
It took me some time to find out what you wanted to accomplish. Here's what I've come up with. Hope it helps.
The problem is that threads in your implementation are trying to acquire lock in some order. So thread waiting for 3 permits waits first, then comes the thread waiting for 2 permits, and obviously stands in line waiting for his 2 permits, then comes the first thread wanting just 1 permit. There is one permit available so it's good to go. Then it returns 2 permits. Unfortunately next in line is thread waiting for 3 permits, not that waiting for 2. Bummer. Blocked. That's what you observe.
If you made other threads to change places in line for acquire, everything would be fine. Here comes
s.tryAcquire(int permits)
and suddenly everything works fine.
I'll make example based on your code, with 1s sleep in busy wait loop to see what's going on.
import java.util.concurrent.Semaphore;
class Process0 extends Thread {
Semaphore s;
public Process0(Semaphore s){
this.s = s;
}
public void run(){
try {
sleep(20000);
s.acquire();
System.out.println("hello");
} catch (InterruptedException ex) {
System.out.println(Process.class.getName());
}
s.release(2);
System.out.println("released 2");
}
}
class Process1 extends Thread{
Semaphore s;
public Process1(Semaphore s){
this.s = s;
}
public void run(){
try {
this.sleep(10000);
while(!s.tryAcquire(2)) {
System.out.println("Busy waiting for 2 permits");
sleep(1000);
}
System.out.println("Hello 2");
} catch (InterruptedException ex) {
System.out.println(Process.class.getName());
}
s.release(3);
System.out.println("Released 3");
}
}
class Process2 extends Thread{
Semaphore s;
public Process2(Semaphore s){
this.s = s;
}
public void run() {
System.out.println("Acquire process 3 ");
while(!s.tryAcquire(3)) {
System.out.println("Busy waiting for 3 permits");
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Hello 3");
}
}
public class DaemonTest {
public static void main(String[] args) {
Semaphore s = new Semaphore(1);
Process0 p = new Process0(s);
Process1 p1 = new Process1(s);
Process2 p2 = new Process2(s);
p.start();
p1.start();
p2.start();
}
}
I have been looking for ways to kill a thread and it appears this is the most popular approach
public class UsingFlagToShutdownThread extends Thread {
private boolean running = true;
public void run() {
while (running) {
System.out.print(".");
System.out.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
}
System.out.println("Shutting down thread");
}
public void shutdown() {
running = false;
}
public static void main(String[] args)
throws InterruptedException {
UsingFlagToShutdownThread t = new UsingFlagToShutdownThread();
t.start();
Thread.sleep(5000);
t.shutdown();
}
}
However, if in the while loop we spawn another another object which gets populated with data (say a gui that is running and updating) then how do we call back - especially considering this method might have been called several times so we have many threads with while (running) then changing the flag for one would change it for everyone?
thanks
One approach with these problems is to have a Monitor class which handles all the threads. It can start all necessary threads (possibly at different times/when necessary) and once you want to shutdown you can call a shutdown method there which interrupt all (or some) of the threads.
Also, actually calling a Threads interrupt() method is generally a nicer approach as then it will get out of blocking actions that throw InterruptedException (wait/sleep for example). Then it will set a flag that is already there in Threads (which can be checked with isInterrupted() or checked and cleared with interrupted(). For example the following code can replace your current code:
public class UsingFlagToShutdownThread extends Thread {
public void run() {
while (!isInterrupted()) {
System.out.print(".");
System.out.flush();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) { interrupt(); }
}
System.out.println("Shutting down thread");
}
public static void main(String[] args)
throws InterruptedException {
UsingFlagToShutdownThread t = new UsingFlagToShutdownThread();
t.start();
Thread.sleep(5000);
t.interrupt();
}
}
i added a utlility class which essentially had a static map and methods.
the map was of type Long id, Thread thread. I added two methods one to add to the map and one to stop the thread via the use of interrupt. This method took the id as a parameter.
I also changed my loop logic from while true, too while ! isInterrupted. Is this approach ok or is this bad programming style/convention
thanks
I am test a scenario to use volatile variable to stop one running thread from another.
I wonder why its not working. Where is the problem?
My code is:
public class StoppableTask extends Thread {
private volatile boolean pleaseStop;
public void run() {
System.out.println("Running..");
while (!pleaseStop) {
System.out.println("Working...");
}
}
public void tellMeToStop() {
pleaseStop = true;
}
}
public class Stopper extends Thread {
StoppableTask t ;
public Stopper(StoppableTask t){
this.t=t;
}
public void run(){
System.out.println("Ok..running too..");
try {
System.out.println("Waiting..");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.tellMeToStop();
System.out.println("Done Waiting..");
}
public class QuickTest{
public static void main(String[] args) {
StoppableTask t = new StoppableTask();
Stopper s = new Stopper(t);
t.start();
s.start();
}
}
I suspect that your program is printing so much output to the terminal that it is blocking waiting for the output to be displayed. It looks like it is not stopping but really it will. You just need to wait... for a long time...
You should put a Thread.sleep(100); inside of of the while() spin loop in StoppableTask.run() to slow down that output. Another way to do it is to remove the System.out and just increment a counter or something.
I just tried it and your program finishes in 5 seconds as expected:
public void run() {
System.out.println("Running..");
while (!pleaseStop) {
// System.out.println("Working...");
}
System.out.println("Stopped task Done");
}
Your program is correct.
When working with threads i suggest you to use log4j instead of system.out.println.Configure the log4j to send output to a file.
You can search your string-pattern in a file. Its easy to analyse.