I know it lot of people have problems with this topic and you might be bored, but I try to understand it since few days and still don't know how it works:(. I have a counter object, and other objects of another class (in the future more then one class). Now each object should respond for counters execution. One count - one step of each objects run method. That's my code:
public class Th {
private final static Object lock1 = new Object();
////////////////////////////////////////////////////////////////////////////////
private class Stop implements Runnable {
private int count, id;
public Stop(int id) {
this.count = 0;
this.id = id;
}
#Override public void run() {
synchronized(lock1){
while (count < 20) {
try {
lock1.wait();
}
catch (InterruptedException exception) {
System.out.println("Error!");
}
System.out.println(count + " stop " + id);
this.count++;
// try {
// Thread.sleep(360);
// }
// catch (InterruptedException exception) {
// System.out.println("Error!");
// }
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
private class Counter implements Runnable {
private int count;
public Counter() {
this.count = 0;
}
#Override public void run() {
synchronized(lock1){
while (count<15) {
lock1.notifyAll();
System.out.println(count + " counter");
this.count++;
// try {
// Thread.sleep(360);
// }
// catch (InterruptedException exception) {
// System.out.println("Error!");
// }
}
}
}
}
public void test() {
Stop s1 = new Stop(1);
Stop s2 = new Stop(2);
Stop s3 = new Stop(3);
Counter counter = new Counter();
(new Thread(s1)).start();
(new Thread(s2)).start();
(new Thread(counter)).start();
(new Thread(s3)).start();
}
}
and it returns me something like:
run:
0 counter
1 counter
2 counter
3 counter
4 counter
5 counter
6 counter
7 counter
8 counter
9 counter
10 counter
11 counter
12 counter
13 counter
14 counter
0 stop 1
what I need is:
0 counter
0 stop 0
0 stop 1
0 stop 2
1 counter
1 stop 0
1 stop 1
1 stop 2
2 counter
2 stop 0
2 stop 1
2 stop 2
3 counter
...
The entire loop of the Counter thread is synchronizd on lock1. This means that although you call notifyAll in this loop, other threads can't reacquire the lock until the complete loop has ended in the Counter thread.
Make each iteration of the loop synchronized, instead of synchronizing outside of the loop.
Note that this won't be sufficient, though, because the Counter thread might reacquire the lock before all the Stop threads have reacquired it. You'll need to make the Counter thread wait on another condition, and make it restart when all the Stop threads have displayed the count.
You should investigate higher-level abstractions, like CyclicBarrier and CountDownLatch.
First, the best way to solve this is to use the higher level synchronization classes, as JB Nizet says.
But if you want to do it "the hard way" as a learning exercise, you need to recognize that this problem requires the Counter and Stop threads to wait for specific "events".
The Stop threads need to wait until the Counter thread tells them to advance to the next stop.
The Counter thread needs to wait until all Stop threads have advanced and stopped.
One problem with your current implementation is that the Counter thread has nothing to tell it when all of the Stop threads have advanced and stopped. Instead, it assumes that when it sees a notify event that it is ok to issue the next count.
Related
I am learning multithreading. I have a following code:
public class Intro {
public static void main(String[] args) {
new Intro().doCounter();
}
private int counter = 0;
synchronized void increment() {
counter++;
}
private void doCounter() {
Thread thread1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 1_000_000; i++) {
increment();
}
System.out.println("first: " + counter);
}
});
Thread thread2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 1_000_000; i++) {
increment();
}
System.out.println("second: " + counter);
}
});
thread1.start();
thread2.start();
}
}
Output (can differ):
first: 1741739
second: 2000000
The code has two threads. One thread increment the counter million times, while the second wait. Then the second increment it million times as well. I understand why the second thread get 2 million, but didn't get why the first thread get 1741739. Why it isn't 1 million for the first thread? I think it had to stop at 1 million. Thanks for explanation.
As discussed in the comments, you have two problems.
You need to understand that threading execution is not predictable. Each thread gets scheduled for a certain amount of time on a CPU core as decided by the JVM and the OS. How often each thread gets scheduled, and for how long, depends on conditions at runtime. So their work can be interleaved, with no guarantee as to which thread will run when, or finish first/last.
Your code is accessing a resource, a member field variable counter across threads without protection. This is not thread-safe. Due to modern CPU architecture and the Java Memory Model, your two threads might see two different states of that single variable. For example, each of two cores running your two threads might each have a different copy of the variable in its cache.
One solution is to use AtomicInteger as your counter variable rather than int. An AtomicInteger is thread-safe, protecting access to its contained int value. By using AtomicInteger, you no longer need your synchronized increment method.
Here is some example code for that.
An Incrementor class that contains our AtomicInteger variable named count as a member field. The class carries nested class IncrementingTask that is a Runnable with a run method to be executed on background threads, incrementing our count var a million times. The class has a demo method for starting any number of threads, each thread running an instance of IncrementingTask to increment the million times.
package work.basil.threading;
import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Incrementor
{
// Member fields.
final private AtomicInteger count = new AtomicInteger( 0 );
public void demo ( )
{
int threadsLimit = 2;
ExecutorService executorService = Executors.newFixedThreadPool( threadsLimit );
for ( int i = 0 ; i < threadsLimit ; i++ )
{
executorService.submit( new IncrementingTask() );
}
executorService.shutdown();
try { executorService.awaitTermination( 1 , TimeUnit.HOURS ); } catch ( InterruptedException e ) { e.printStackTrace(); }
// At this point, the tasks are all done/canceled/failed.
System.out.println( "RESULTS: count is at: " + this.count.get() );
}
// Runnable task.
class IncrementingTask implements Runnable
{
#Override
public void run ( )
{
for ( int i = 0 ; i < 1_000_000 ; i++ )
{
int incrementedCount = count.incrementAndGet();
if ( i % 100_000 == 0 )
{
System.out.println( "Thread # " + Thread.currentThread().getId() + " incremented count to: " + incrementedCount + " at " + Instant.now() );
}
}
System.out.println( "Thread # " + Thread.currentThread().getId() + " is done incrementing. " + Instant.now() );
}
}
}
A class to run this.
package work.basil.threading;
public class App
{
public static void main ( String[] args )
{
App app = new App();
app.demo();
}
private void demo ( )
{
Incrementor incrementor = new Incrementor();
incrementor.demo();
}
}
When run.
Thread # 15 incremented count to: 2 at 2021-03-29T00:04:37.099350Z
Thread # 14 incremented count to: 1 at 2021-03-29T00:04:37.099281Z
Thread # 14 incremented count to: 200002 at 2021-03-29T00:04:37.155680Z
Thread # 15 incremented count to: 198267 at 2021-03-29T00:04:37.155659Z
Thread # 15 incremented count to: 387108 at 2021-03-29T00:04:37.165850Z
Thread # 14 incremented count to: 400002 at 2021-03-29T00:04:37.165894Z
Thread # 15 incremented count to: 552150 at 2021-03-29T00:04:37.168378Z
Thread # 14 incremented count to: 631000 at 2021-03-29T00:04:37.169329Z
Thread # 15 incremented count to: 753457 at 2021-03-29T00:04:37.170931Z
Thread # 14 incremented count to: 840455 at 2021-03-29T00:04:37.171943Z
Thread # 15 incremented count to: 942263 at 2021-03-29T00:04:37.173276Z
Thread # 14 incremented count to: 1049089 at 2021-03-29T00:04:37.174559Z
Thread # 15 incremented count to: 1135900 at 2021-03-29T00:04:37.175726Z
Thread # 14 incremented count to: 1240800 at 2021-03-29T00:04:37.177092Z
Thread # 15 incremented count to: 1308191 at 2021-03-29T00:04:37.177678Z
Thread # 15 incremented count to: 1439696 at 2021-03-29T00:04:37.179523Z
Thread # 15 incremented count to: 1595283 at 2021-03-29T00:04:37.180795Z
Thread # 14 incremented count to: 1604140 at 2021-03-29T00:04:37.181720Z
Thread # 14 incremented count to: 1800001 at 2021-03-29T00:04:37.183231Z
Thread # 14 incremented count to: 1900001 at 2021-03-29T00:04:37.184697Z
Thread # 15 is done incrementing. 2021-03-29T00:04:37.182735Z
Thread # 14 is done incrementing. 2021-03-29T00:04:37.188265Z
RESULTS: count is at: 2000000
Notice that every time we run this, we always get to exactly 2,000,000 million total. Also notice that every time you run this, the list of which thread ran when will vary, as will the count at each time the thread reports to us on the console.
Console lies
Notice the counts look crazy. The first two lines report a count of 2 and then 1 rather than one then two. Same with the third and fourth lines, apparently backwards.
Look more closely to examine the microseconds of the timestamps. Those timestamps are not in chronological order.
Lesson learned: The System.out.println calls do not present on the console in chronological order. So never rely on such console output to give you a true picture of what happened when.
Always include a timestamp such as Instant.now() or System.nanoTime(). If you want to see messages in order, collect them in a thread-safe ordered collection such as Collections.synchronizedList​( new ArrayList< String >() ).
Alternatively, if you wanted to keep your int variable and synchronized increment method rather than use AtomicInteger you must protect access to the counter variable in a thread-safe manner. Marking the variable as volatile would help. You can search Stack Overflow to learn more on this.
public class Bank {
private int sum=0;
public void add(int n) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
sum+= n;
System.out.println(sum);
}
}
public class Consumer implements Runnable {
Bank bank = new Bank();
#Override
public void run() {
for (int i = 0; i < 10; i++) {
bank.add(100);
}
}
}
public class Tes2 {
public static void main(String[] args) {
Consumer consumer = new Consumer();
Thread thread1 = new Thread(consumer);
Thread thread2 = new Thread(consumer);
thread1.start();
thread2.start();
}
}
This is a multithreaded program, simulation is multiple depositors to the bank to deposit money, used to demonstrate multithreaded security issues.Since the code is not synchronized, its first and second results might be 200/200,200/300, and so on.But I don't understand why you get 100/100, who can explain?
This is a race condition.
Both threads have access to sum.
sum += n; is not atomic
Thread 1 reads sum 0
Thread 2 swaps in because the code isnt synchronized reads sum as 0
Thread 1 adds 100 to 0 and writes that to sum
Thread 2 adds 100 to 0 and writes that to sum overwriting thread 1s value
If you think about the concurrency of this program just based on the lines in the code, the 100/100 output result wouldn't make sense. But you also have to think about what instructions are actually happening when these lines are being performed. Each line of code can consist of many, many assembly instructions. In this case, to add n to sum, what really happens is that the value of sum is read from memory, probably loaded onto a register, incremented, then re-written onto memory.
The 100/100 output can happen in the following scenario. Let's say thread 1 and thread 2 both call bank.add(100), and the bank handles requests asynchronously. That is, the bank has a thread handling each request.
Then, thread 1 of the bank loads the value of sum, which is zero. Thread 2 also loads the value of sum right after, which is still zero. Then, thread 1 takes the value it loaded, adds n=100, and writes it into memory. Thread 2 does the same; it takes the value of sum it loaded previously, 0, adds 100, then writes it back onto memory. Then, they each print out the value of 100.
I have thread x which I start like so:
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(() -> {
Inside x I have a CyclicBarrier with another 10 threads:
final CyclicBarrier _threadGate = new CyclicBarrier(10);
ArrayList<Thread> _threadList = new ArrayList<>();
Then I add the thread to the list
for (int i = 0; i < 10; i++) {
_threadList.add(new Thread() {
#Override
public void run() {
_threadGate.await();
//long processing code
So after the threads are ready I start them, it is important for them to start at the same time (well almost, looping takes time, even if its 0,01ms):
for (int i = 0; i < _threadList.size(); i++) {
_threadList.get(i).start();
}
Now, the end of x, the main thread, is like this:
}, 0, repeatTimer, TimeUnit.SECONDS);
If repeatTimer is 300 this means that it starts again the 10 threads after 5 minutes.
The time for the 10 threads to finish is an UNKNOWN amount, but it is under 5 minutes. Somewhere between 2 and 4 minutes for sure.
What I want to achieve
Once the 10 threads finish, restart X but with a delay of 5 seconds.
For this I have been thinking of setting the repeatTimer value to the time elapsed by the 10 threads + 5 seconds (I dont know how to do it, I dont know w hen last thread finishes its task), but is this correct? or is there another way of doing it?
I don't see the necessity of having SchedulingExecutorService here. You can just wait until all threads finish their job using CountDownLatch.
Here's a simple exapmple:
while (!stopped) {
CountDownLatch latch = new CountDownLatch(N);
// create and start your threads
latch.await(); // this method blocks until each Thread calls countDown()
// wait here 5 seconds if you want
}
Decrement the latch in last action of each thread:
public void run() {
_threadGate.await();
// thread actions
latch.countDown();
}
SOLVED !
I have a homework. I will say shortly what is about. I have to read from .txt file few numbers, and multiply them. I need to use threads and synchronize that multiplication only. I done that already and my homework ends here! But, I want to go ahead and create a more complex way for example:
I have in .txt numbers like this: 5, 6, 2, 11, 24, 10,
and then I multiply them like this 5*6*2*11*24*10 .
How can I create 2 threads, Thread #1 for numbers, and Thread #2 for multiply, and print them in console like this:
Thread #1 running, number is 5
Thread #2 running, multiply is 5
Thread #1 running, number is 6
Thread #2 running, multiply is 30
Thread #1 running, number is 2
Thread #2 running, multiply is 60
I really appreciate any suggestion, past 10 h since I work at this and still can't get it work.
class MyThread extends Thread {
Thread thread;
MyThread(String name) {
thread = new Thread(this, name);
}
public synchronized void numbers(boolean running) {
if (!running) {
notify();
return;
}
notify();
try {
FileInputStream fs = new FileInputStream("in.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String line;
int numbers = 0;
while ((line = br.readLine()) != null) {
String[] splitter = line.split("\\s");
numbers = Integer.parseInt(splitter[0]);
for (int i = 0; i <= splitter.length - 1; i++) {
numbers = Integer.parseInt(splitter[i]);
System.out.print("\nIn " + thread.getName() + "number is " + numbers + "\t");
Thread.sleep(500);
}
}
} catch (InterruptedException e) {
System.out.println("main thread interrupted");
} catch (IOException e) {
System.out.println("main thread interrupted");
}
}
public synchronized void multiply(boolean running) {
if (!running) {
notify();
return;
}
notify();
try {
FileInputStream fs = new FileInputStream("in.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String line;
int numbers = 0;
int multiply = 1;
while ((line = br.readLine()) != null) {
String[] splitter = line.split("\\s");
numbers = Integer.parseInt(splitter[0]);
for (int i = 0; i <= splitter.length - 1; i++) {
numbers = Integer.parseInt(splitter[i]);
multiply = multiply * numbers;
System.out.print("\nIn " + thread.getName() + " multiply is " + multiply + "\t");
Thread.sleep(500);
}
}
} catch (InterruptedException e) {
System.out.println("main thread interrupted");
} catch (IOException e) {
System.out.println("main thread interrupted");
}
}
synchronized public void run() {
if (thread.getName().compareTo("Thread #1 ") == 0) {
for (int i = 0; i < 1; i++)
this.numbers(true);
this.numbers(false);
} else {
for (int i = 0; i < 1; i++)
this.multiply(true);
this.multiply(false);
}
}
}
My code look like this:
In main I call like this:
MyThread mt1 = new MyThread("Thread #1 ");
MyThread mt2 = new MyThread("Thread #2 ");
mt1.start();
mt2.start();
At this moment , my output look like this:
In Thread #2 multiply is 5
In Thread #1 number is 5
In Thread #1 number is 6
In Thread #2 multiply is 6
In Thread #2 multiply is 30
In Thread #1 number is 2
In Thread #1 number is 11
In Thread #2 multiply is 660
In Thread #2 multiply is 15840
In Thread #1 number is 24
The problem is that you're trying to use one implementation for both tasks. I would suggest to create ReadThread that will read the input file and MultiplyThread that will wait for some event for example and multiply numbers. Also they will need to share some collection of the numbers (see ConcurrentLinkedQueue for example).
So ReadThread read a number from file, adds it to the queue. At the same time MultiplyThread waits for anything to appear in the same queue and when this happens multiply new number on the previous one. There is also will be improvements on the design, because without much effort we can replace MultiplyThread with let's say AddThread that will calculate sum of the numbers.
However your implementation trying to do both tasks in one class which highly increases complexity. Also try to get rid of synchronized and Thread.sleep statements, in your case they will decrease the performance and there would be no point in using multithreading.
Here is example implementation for the method I've suggested.
First is the ReadThread. It has the queue that will contain numbers that have to be processed. I have simplified the reading of the numbers from the file, you can replace it with you reading implementation.
class ReadThread implements Runnable {
private final String filename;
private final ConcurrentLinkedQueue<Integer> queue;
public ReadThread(ConcurrentLinkedQueue<Integer> queue, String filename) {
this.queue = queue;
this.filename = filename;
}
public void run() {
try {
FileInputStream fs = new FileInputStream(filename);
Scanner scanner = new Scanner(fs);
while (scanner.hasNextInt()) {
int number = scanner.nextInt();
System.out.println("ReadThread read " + number);
queue.add(number);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
And the MultiplyThread. Here we take the number from the queue and multiply it on the result which stores the previous value. There is the problem with thread life cycle - we don't know when it should be stopped. So I have used simple active flag. Which tells the thread when to stop.
class MultiplyThread implements Runnable {
private boolean active = true;
private Integer result = 1;
private final Queue<Integer> queue;
public MultiplyThread(ConcurrentLinkedQueue<Integer> queue) {
this.queue = queue;
}
public void run() {
while (isActive()) {
Integer number = queue.poll();
if (number != null) {
result *= number;
System.out.println("MultiplyThread current result is " + result);
}
}
}
public synchronized void stop() {
active = false;
}
public synchronized boolean isActive() {
return active;
}
}
And here is the last part. It's more complex then yours, because of MultiplyThread interruption.
public static void main(String[] args) throws InterruptedException {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
ReadThread readThread = new ReadThread(queue, "numbers.txt");
MultiplyThread multiplyThread = new MultiplyThread(queue);
Thread reader = new Thread(readThread);
Thread multiplicator = new Thread(multiplyThread);
multiplicator.start();
reader.start();
reader.join();
multiplyThread.stop();
multiplicator.join();
}
The result of the program
ReadThread read 1
ReadThread read 2
MultiplyThread current result is 1
MultiplyThread current result is 2
ReadThread read 3
MultiplyThread current result is 6
ReadThread read 4
MultiplyThread current result is 24
ReadThread read 5
MultiplyThread current result is 120
ReadThread read 6
MultiplyThread current result is 720
ReadThread read 7
MultiplyThread current result is 5040
You can see that thread are working concurrently, ReadThread does not wait MultiplyThread to calculate the result for all previous values.
It is not clear what you are trying to do. There are some obvious mistakes in the code which i want to highlight (and hence writing this answer), but I can't answer the question as the code seems to do what it was written to do: it runs 2 threads, both read from the same file and output results of reading in slightly different ways.
Now to the problems:
1) if you are extending Thread you should not have a thread field inside of it. Basically you can replace thread = new Thread(this ,name); with super(name).
2) your synchronized doesn't do anything. Synchronized makes method enter a monitor (essentially acquire object lock) when you enter the method and release it when method is done. Your two threads are 2 different instances which share no data between each other, so synchronizeds are not doing anything.
The way you've written your code, the two threads aren't really "connected", they don't share any memory. They read both the same file, but that's all - no shared memory. From what I guess, the idea would rather to have a "producer" thread which reads data from the file, and a "consumer" thread which get data read by the first thread and execute the multiplication. The second thread should not read the file.
You could write something with a shared AtomicInteger: when empty (null), the "producer" thread set it to what it has read ; and when non empty, the "consumer" thread read it, reset it to empty, and can run its multiplication.
I am working on a drawing application, using Java and Swing. It has a constant update loop that runs constantly, as long as a boolean variable is set to true. The loop is located inside a thread.
It works fine, but now I want the loop to only run at certain times (only when the mouse is pressed), and otherwise not run. (Thus not wasting memory for nothing).
To stop the loop, I can simply set that variable to false. But my question is, how can I restart the loop after stopping it? Setting that variable back to true will not restart the loop. What would be a good way to do this?
EDIT: My (a little simplified) loop:
public void run(){
int TICKS_PER_SECOND = 50;
int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
int MAX_FRAMESKIP = 10;
long next_game_tick = System.currentTimeMillis();
int loops;
boolean app_is_running = true;
while( app_is_running ) {
loops = 0;
while( System.currentTimeMillis() > next_game_tick && loops < MAX_FRAMESKIP) {
update();
next_game_tick += SKIP_TICKS;
loops++;
}
repaint();
}
}
Use Object.wait to suspend the thread when it isn't running. Have another thread call Object.notify to wake it up from its sleep.
To execute the thread body once every FRAME_RATE ms while being controllable by an externally defined Boolean, the run method could be structured as such:
public void run()
{
long delay;
long frameStart = System.currentTimeMillis();
// INSERT YOUR INITIALIZATION CODE HERE
try
{
while (true)
{
if (active) // Boolean defined outside of thread
{
// INSERT YOUR LOOP CODE HERE
}
frameStart += FRAME_RATE;
delay = frameStart - System.currentTimeMillis();
if (delay > 0)
{
Thread.sleep(delay);
}
}
}
catch (InterruptedException exception) {}
}
Additionally, if you want to eliminate the slight overhead of the constantly running loop (for a mostly inactive thread), the Boolean in the while loop could be replaced with a Semaphore object:
while (true)
{
semaphore.acquire(); // Semaphore defined outside thread with 1 permit
// INSERT YOUR LOOP CODE HERE
semaphore.release();
frameStart += FRAME_RATE;
delay = frameStart - System.currentTimeMillis();
if (delay > 0)
{
Thread.sleep(delay);
}
}
To stop the loop externally use semaphore.acquire(); to restart it use semaphore.release().