I got 2 classes:
First class I invoke Constructor in LogScheduler - is Singleton, constructor create new Thread and start it. Main Thread going sleep on 5 sec, then i set boolean variable false to stop loop:
public class Launch {
public static void main(String[] args) throws InterruptedException {
LogScheduler log = LogScheduler.getInstance();
Thread.sleep(5000);
log.setActive(false);
List<String> logs = log.getLogs();
logs.add("ABBA");
log.showLogs();
}
}
Second class:
public class LogScheduler {
public static final LogScheduler INSTANCE = new LogScheduler();
private final List<String> logs = new ArrayList<>();
private final Thread worker;
private boolean active = true;
private int i = 0;
private LogScheduler() {
addLog("Launch");
worker = new Thread(this::log);
worker.setName(getClass().getName());
worker.start();
}
private void log() {
addLog("Start");
while (active) {
synchronized (worker) {
try {
System.out.println(Thread.currentThread()
.getName() + " - " + i++);
worker.wait(1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
addLog("End");
}
public void addLog(String value) {
logs.add(value);
}
public void showLogs() {
logs.forEach(System.out::println);
}
public List<String> getLogs() {
return logs;
}
public void setActive(boolean active) {
this.active = active;
}
public static LogScheduler getInstance() {
return INSTANCE;
}
public Thread getWorker() {
return worker;
}
}
Console Out:
job.LogScheduler - 0
job.LogScheduler - 1
job.LogScheduler - 2
job.LogScheduler - 3
job.LogScheduler - 4
Launch
Start
ABBA
'End' - word in log() method doens't display in console.
Give some advice to fix it please. I try synchronized logs variable and addLog method, it doesn't help.
When you set active to false, you don't give enough time to the logger to see that change. It is waiting in worker.wait he you set active to false, and move on to finish the program.
You have to notify the worker when you set active:
public void setActive(boolean active) {
synchronized(worker) {
this.active = active;
worker.notify()
}
}
So when you change active, the worker.wait is notified.
However, even with this there are executions where the last log will be printed and there are executions where last log will not be printed, because your program may terminate before the worker has a chance to add the last log. You need further synchronization to guarantee that, or you can wait a bit before returning from main.
You do have a data race as well. When you add/read logs you are not synchronizing the access to the shared log list. Either synchronize access to it, or use a synchronized collection to store logs.
When you call log.getLogs() the "End" has not been written yet. To illustrate that you can try this main function where i add an other sleep before log.getLogs() which will give enought time to write "End" :
public class Launch {
public static void main(String[] args) throws InterruptedException {
LogScheduler log = LogScheduler.getInstance();
Thread.sleep(5000);
log.setActive(false);
//new sleep
Thread.sleep(5000);
List<String> logs = log.getLogs();
logs.add("ABBA");
log.showLogs();
}
}
Related
I was going through one of the tutorials on memory model of Java and came across this concept of field visibility which happens in multi-threaded programming. I tried to simulate the same using the below code, however , I see in each thread, the latest value is being reflected (in ReaderThread).
The below is the complete program.
Edit
After some suggestion to use while(somevariable), I incorporated, but still getting the same behaviour. I removed sysout on reading the x
FieldVisibility.java
package com.example.threads.fieldvisibility;
public class FieldVisibility {
private int x;
private boolean condition;
public FieldVisibility() {
condition = true;
}
public void reader() {
System.out.println("x in reader() is " + x);
}
public void writer() {
x++;
}
public boolean getCondition() {
return condition;
}
public void setCondition(boolean condition) {
this.condition = condition;
}
}
ReaderThread.java
package com.example.threads.fieldvisibility;
public class ReaderThread extends Thread {
private FieldVisibility fv;
public ReaderThread(FieldVisibility fv) {
this.fv = fv;
}
#Override
public void run() {
while (fv.getCondition()) {
System.out.println("It mean condition is true, which was set initially");
}
for (;;) {
}
}
}
WriterThread.java
package com.example.threads.fieldvisibility;
public class WriterThread extends Thread {
private FieldVisibility fv;
public WriterThread(FieldVisibility fv) {
this.fv = fv;
}
#Override
public void run() {
fv.setCondition(false);
for (;;) {
fv.writer();
}
}
}
MainApp.java
package com.example.threads.fieldvisibility.main;
import com.example.threads.fieldvisibility.FieldVisibility;
import com.example.threads.fieldvisibility.ReaderThread;
import com.example.threads.fieldvisibility.WriterThread;
public class MainApp {
public static void main(String[] args) throws InterruptedException {
FieldVisibility fv = new FieldVisibility();
ReaderThread rt = new ReaderThread(fv);
WriterThread wt = new WriterThread(fv);
wt.start();
rt.start();
Thread.sleep(999999999L);
}
}
Edit
I added a new variable condition in FieldVisibility, whose default values is true. Next, I set its value to false in WriterThread, however, the same value (false) is still propagated to ReaderThread, so I still am not able to simulate it.
Original
I expected that at some time ReaderThread won't be able to "see" the latest value of variable x, but I saw every time I run it, it gave same results. I even run in debug mode, suspended ReaderThread while running WriterThread continuously. But that also didn't prevent ReaderThread to have latest values. I expected that I need to declare variable x as volatile in order for ReaderThread to read latest values of x.
How can I simulate the field visibility concept, or what changes I need to do for this?
Your example doesn't work because System.out.println() uses a shared resource (System.out), so it will synchronize with other uses of the same resource.
Therefore you will never* see a result where one thread uses the old value of the other. (*in theory it is possible for the reader to read x between x++ and the corresponding System.out.println()
Here is an example where a old value is used:
public class ThreadVisibility implements Runnable {
private boolean stop = false;
#Override
public void run() {
while (!stop);
}
public static void main(String[] args) throws InterruptedException {
ThreadVisibility test = new ThreadVisibility();
Thread t = new Thread(test);
t.setDaemon(true);
System.out.println("Starting Thread");
t.start();
Thread.sleep(1000);
System.out.println("Stopping Thread");
test.stop = true;
t.join(1000);
System.out.println("Thread State: " + t.getState());
}
}
If you run this code, it will display that the thread is still running at the end. Without the t.setDaemon(true), the VM would wait for the Thread to finish, which would never happen.
If you comment out the Thread.sleep, then the new Thread may terminate (at least it did in my tests), but it is not guaranteed to.
The right fix for this problem is to declare stop volatile.
Or add a memory barrier.
I tried using a volatile boolean to act as a flag to stop/start/restart the action in the thread, however it does not work. It just keeps on going forever and never terminates. Any help on how to properly do this or why my code does not work will be greatly appreciated. Thanks in advance.
public class thread {
public static int i = 0;
private static Thread print = null;
private static printThread runnable = null;
public static void main(String[] args) {
runnable = new printThread();
print = new Thread (runnable);
print.start();
System.out.println("Starting");
runnable.begin();
if(i > 5)
{
runnable.terminate();
}
i = 10;
runnable.begin();
if(i > 15)
{
runnable.terminate();
}
}
public static final void print()
{
System.out.println(i);
i++;
}
public static final class printThread implements Runnable {
private volatile boolean running = false;
public void terminate() {
running = false;
}
public void begin() {
running = true;
}
public boolean isRunning() {
return running;
}
public void run() {
while(true)
{
if(running)
{
print();
}
else
{
}
}
}
}
}
In your code while loop execution never ends. You could introduce 2 states: terminated and waiting to simulate threads start/pause/restart/stop. However, even if you pause the Thread it will be running, just different branch of code will be executed inside while loop.
Please, see the code snippet below
public static final class printThread implements Runnable {
private volatile boolean waiting = false;
private volatile boolean terminated = false;
public void terminate() {
terminated = true;
}
public void pause() {
waiting = true;
}
public void restart() {
waiting = false;
}
public void run() {
while(!terminated) {
if(waiting) {
//the thread is paused
} else {
//the thread is running
}
}
}
}
however it does not work. It just keeps on going forever and never terminates.
In your run() method of your thread, you aren't watching for the value of your volatile boolean running field. It probably should be something like:
public void run() {
while(!running) {
print();
// you might want a short Thread.sleep(10); here to stop the spinning
}
}
However, as #Anton points out, once your thread terminates, it can't be restarted without some other flag. See his answer.
Also, you are sharing i between the main thread and the your printing thread. That also needs to be volatile so it can be properly shared. Since you are incrementing it in multiple threads, you should use an AtomicInteger for that.
public static AtomicInteger i = new AtomicInteger();
...
if (i.get() > 5) ...
...
i.set(10);
...
i.incrementAndGet();
Couple of other comments:
Be careful of static fields. print and runnable should be defined only inside of the main(...) method to restrict access.
Classes should begin with an uppercase letter so it should be PrintThread.
Actually, because PrintThread isn't a thread, it should be PrintRunnable or maybe even better, Printer.
I am trying to test BrokenBarrierException by resetting the cyclicbarrier in the middle of starting (awaiting) few parties (threads), please find the below sample code for the same.
User class:
public class User implements Runnable {
private final String name;
private final CyclicBarrier cb;
public User(String name, CyclicBarrier cb) {
this.name = name;
this.cb = cb;
}
#Override
public void run() {
System.out.println(name+" user started !!!! ");
try {
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
System.out.println(e);
e.printStackTrace();
}
}
}
CyclicBarrierTest class:
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5);
User user1 = new User("USER1", barrier);
new Thread(user1).start();
User user2 = new User("USER2", barrier);
new Thread(user2).start();
//Expected users are 5, but only 2 user threads started so far
// and resetting below which should throw barrier broken exception
barrier.reset();
if(barrier.isBroken()) {
System.out.println("Barrier broken ");
}
}
}
So, after running the main() above, I could get any exceptions and also "Barrier broken" also not printed. The threads are simply waiting.
I have referred the CyclicBarrier API below link:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html
public void reset():
Resets the barrier to its initial state. If any
parties are currently waiting at the barrier, they will return with a
BrokenBarrierException.
But my above code doesn't seems to work according to the API description, so what is the problem with my above code and why it is NOT throwing BrokenBarrierException ?
Could you please help ?
If you want exception thrown , you have to make sure barrier.reset(); executes after cb.await(); , but here System.out.println(name+" user started !!!! "); is a very costly statement which makes barrier.reset(); executes too early , you can add a sleep statement before barrier.reset(); , say Thread.sleep(100);.
Doc of isBroken :
true if one or more parties broke out of this barrier due to interruption or timeout since construction or the last reset, or a barrier action failed due to an exception; false otherwise.
If you want it as broken , you can do something to the parties . You need remove reset to make threads awaiting .
public class User implements Runnable {
private final String name;
private final CyclicBarrier cb;
public User(String name, CyclicBarrier cb) {
this.name = name;
this.cb = cb;
}
#Override
public void run() {
System.out.println(name+" user started !!!! ");
try {
cb.await(1,TimeUnit.SECONDS);
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+" user ended !!!! ");
}
}
public class CyclicBarrierTest {
public static void main(String[] args) throws Exception {
CyclicBarrier barrier = new CyclicBarrier(5);
User user1 = new User("USER1", barrier);
new Thread(user1).start();
User user2 = new User("USER2", barrier);
new Thread(user2).start();
//Expected users are 5, but only 2 user threads started so far
// and resetting below which should throw barrier broken exception
Thread.sleep(100);
// barrier.reset();
Thread.sleep(1100);
if(barrier.isBroken()) {
System.out.println("Barrier broken ");
}
}
}
Short answer:
On reset the barrier loses the information of previous BrokenBarrierException(s). So any call to isBroken after reset will return false.
The javadoc specify this, although, not very clearly:
isBroken return: true if one or more parties broke out of this barrier due to interruption or timeout since construction or the last reset, or a barrier action failed due to an exception; false otherwise.
Long answer:
You can see more clearly what happens if you look at source code of reset and isBroken:
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
private static class Generation {
boolean broken = false;
}
public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return generation.broken;
} finally {
lock.unlock();
}
}
You can see that the reference generation.broken holds the information about a broken barrier. But this is reinitialized to false on reset.
Hi I'm using the next code to try to stop a thread, but when I see that Running is false it becomes true again.
public class usoos {
public static void main(String[] args) throws Exception {
start();
Thread.sleep(10000);
end();
}
public static SimpleThreads start(){
SimpleThreads id = new SimpleThreads();
id.start();
System.out.println("started.");
return id;
}
public static void end(){
System.out.println("finished.");
start().shutdown();
}
}
And the thread
public class SimpleThreads extends Thread {
volatile boolean running = true;
public SimpleThreads () {
}
public void run() {
while (running){
System.out.println("Running = " + running);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
}
System.out.println("Shutting down thread" + "======Running = " + running);
}
public void shutdown(){
running = false;
System.out.println("End" );
}
}
The problem is that when I try to stop it(I set running to false), it starts again..
Look at this line in the end method:
start().shutdown();
You are not stopping the original instance; you are starting another one, which you then immediately shut down.
There is no connection between your start and end methods—no information, no reference is passed from one to the other. It is obviously impossible to stop the thread you started in the start method.
Your end method should not be static; in fact, you don't even need it, shutdown is already it:
SimpleThreads t = start();
Thread.sleep(10000);
t.shutdown();
Because in the end method you just create a new Thread and kill it, save the thread instance and kill it:
Your code should look something like this:
public class usoos {
public static void main(String[] args) throws Exception {
SimpleThreads id = start();
Thread.sleep(10000);
end(id);
}
public static SimpleThreads start(){
SimpleThreads id = new SimpleThreads();
id.start();
System.out.println("started.");
return id;
}
public static void end(SimpleThreads id){
System.out.println("finished.");
id.shutdown();
}
I can't figure out what is the problem in the following code:
I have a thread that can be suspended and resumed
Code bellow:
public class CustomThread implements Runnable {
private volatile boolean stop;
private volatile boolean suspend;
String[] names = new String[]{
"A", "B","C","D","E", "F", "G","H","I","J","K", "L"
};
public CustomThread(){
Collections.shuffle(Arrays.asList(names));
System.out.println("Available names:");
System.out.println(Arrays.asList(names));
}
#Override
public void run() {
while(!stop){
synchronized (this) {
if(suspend){
try {
System.out.println("Got suspended");
wait();
System.out.println("Resumed");
} catch (InterruptedException e) {
System.out.println("Got interupted");
}
}
else System.out.println("Suspend false");
}
int randomIdx = new Random().nextInt(names.length);
System.out.println(names[randomIdx]);
}
}
public synchronized void suspend(){
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>Suspend true");
suspend = true;
}
public synchronized void resume(){
suspend = false;
notify();
}
}
I run the following simple code:
public class CustomTest {
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
CustomThread c = new CustomThread();
Thread t = new Thread(c);
t.start();
Thread.sleep(5000);
System.out.println("++++++++++++++++++++++++++++++++");
c.suspend();
}
}
What I am expecting to see is:
Thread custom runs, main sleeps, main suspends the custom thread by c.suspend() and since main terminates and noone resumes the thread, the thread remains in wait state.
But what I see instead is that the CustomThread prints continually Suspend false and an element from names.
What is the problem here? It is like the Thread.sleep(5000) and c.suspend() in main don't do anything.
The code is fine as written, but your problem is probably that you are running this through Eclipse and you are overwhelming the console. Put a shorter delay in main and you'll see good results.
Note: your suspend method doesn't need to be synchronized as it only writes to a volatile variable.
Instead of if(suspend) you should have while(suspend), see the explanation in javadoc here: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait%28%29
From the javadoc of Object.wait():
...interrupts and spurious wakeups are
possible, and this method should always be used in a loop