This question already has answers here:
Code to simulate race condition in Java thread
(4 answers)
Closed 6 years ago.
I am trying to make a thread race, but my threads run in order instead of running in parallel ...After a thread finishes the race , it has to inform the context and the context should announce the winner and stop the race . How can I repair this ?
My ThreadRaceClass:
public class ThreadRace {
List<ThreadRaceCompetitor> competitors = new ArrayList<>(10);
public ThreadRace() {
for (int i = 0; i < 10; i++) {
competitors.add(new ThreadRaceCompetitor());
}
}
public void start() {
competitors.forEach(ThreadRaceCompetitor::run);
}
}
The ThreadCompetitor object:
public class ThreadRaceCompetitor implements Runnable {
private static final ThreadRaceContext context = new ThreadRaceContext();
private static AtomicInteger count = new AtomicInteger(0);
private int raceNumber;
private int progress = 0;
public ThreadRaceCompetitor() {
raceNumber = count.incrementAndGet();
}
#Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("Thread " + raceNumber + " is running with " + i + " speed and has covered " + progress + " kilometers / 20" );
try {
sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
progress++;
}
synchronized (context) {
context.announceWinner(raceNumber);
}
}
public int getRaceNumber() {
return raceNumber;
}
public int getProgress() {
return progress;
}
}
And the context:
public class ThreadRaceContext extends Thread {
public void announceWinner(int raceNumber) {
System.out.println("Competitor with number " + raceNumber + " won the race");
}
}
You have to call the start-method. Then it should work.
public void start() {
competitors.forEach(ThreadRaceCompetitor::start); // not sure if that is possible...
}
//alternative
public void start() {
for(ThreadRaceCompetitor c: competitors) {
c.start();
}
}
First of all you are not creating any Thread here. Just by implementing runnable will not make an instance of a class Thread. Using your runnable you have to create an instance of Thread and start it.
One way to achieve this with your existing code is to make your ThreadRaceCompetitor extend Thread and in your ThreadRace class's start method call start method on each ThreadRaceCompetitor in the list instead of calling run directly.
Related
public class driver{
public static void main(String[] args) {
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
PrintNum secondObjectForThread = new PrintNum(0);
secondObjectForThread.startNewThread();
}
This is the class that the driver calls:
public class ClassName implements Runnable{
int variableForUpdate;
private Thread t;
private static ArrayList<Integer> intArray;
public ClassName(int variableForUpdate) {
super();
this.intArray = new ArrayList<Integer>();
this.variableForUpdate = variableForUpdate;
for (int i = 0; i < 30 ; i++) {
this.intArray.add(i);
}
}
#Override
public void run() {
runThisWhenThreadStarts();
}
private synchronized void runThisWhenThreadStarts() {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
public void startNewThread() {
t = new Thread(this);
t.start();
}
}
If I use block synchronization the following, the output is synchronized:
private void runThisWhenThreadStarts() {
synchronized (ClassName.class) {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
}
I have been troubleshooting this for many hours and cannot figure out... Can anyone shed some light please?
I also notice if I use the same object to call startNewThread(), the synchronization will work. But I don't understand why.
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
firstObjectForThread.startNewThread();
I want to use two different object from the same class instead of one object calling the method twice (the workaround above).
I am able to use the synchronized methods in another program, with 2 different instances (get and put) :
public class Hello extends Thread {
int x;
Coffee x1;
int threadno;
Hello(int x, Coffee x1) {
this.x = x;
threadno = x;
this.x1 = x1;
}
public void run() {
switch (x) {
case 0:
System.out.println("Start thread " + threadno + " Get");
break;
case 1:
System.out.println("Start thread " + threadno + " Put");
break;
}
ops();
System.out.println("Stopping thread " + threadno);
}
public void ops() {
x1.get();
}
public static void main(String[] args) {
Coffee c1 = new Coffee();
Hello get = new Hello(0, c1);
Hello put = new Hello(0, c1);
get.start();
put.start();
}
}
Hello class will call coffee class:
class Coffee {
boolean available = false; // indicating there nothing to get.
// waiting on each other.
int contents = 55;
public synchronized int get() {
System.out.println("Entering Get method " + contents);
for (int i = 0; i < 30; i++) {
System.out.println(i);
}
return contents;
}
}
In the first example, the method acquires the lock on the object instance that the method is called on. The block doesnt do that, instead it acquires the lock on the class.
Taking the lock on the instance has no effect on the other thread, it is a different object. Both threads are acquiring their own lock, which is useless. Neither thread is prevented from doing anything.
Taking the lock on the class means both threads are trying to acquire the same lock. For locking to work the same lock has to be used by both threads.
In the second example the Coffee object is shared by both threads, and both threads are trying to acquire the same lock on the Coffee object. That means the second thread to get to the lock has to block until the lock is released by the first thread, locking successfully keeps the thread out until the first thread is done.
To understand synchronized, keep track of what locks are being acquired.
Trying to make a simple multi-threaded programme where it prints Factorial series where each number is printed by different Thread and at the end I am giving a report of which number printed by which thread.I have got the desired output but somehow my program is not terminating.
Constraint: I am not allowed to use Concurrent Package
import java.util.ArrayList;
import java.util.Scanner;
class Report {
private long factorial;
private String threadName;
private int activeThreads;
public Report(long factorial, String threadName, int activeThreads) {
this.factorial = factorial;
this.threadName = threadName;
this.activeThreads = activeThreads;
}
public long getFactorial() {
return factorial;
}
public String getThreadName() {
return threadName;
}
public int getActiveThreads() {
return activeThreads;
}
public void setActiveThreads(int activeThreads) {
this.activeThreads = activeThreads;
}
}
public class Factorial implements Runnable {
public static ArrayList<Report> report = new ArrayList<Report>();
private static int count;
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("N: ");
int n = in.nextInt();
count = n;
Factorial f = new Factorial();
f.series(n);
Thread.sleep(1000);
// Series
for(Report r : report) {
if(r.getFactorial() == 1) {
System.out.print(r.getFactorial());
}
else {
System.out.print(r.getFactorial() + "*");
}
}
System.out.println();
// Report
for(Report r : report) {
System.out.println(r.getFactorial() + " printed by " + r.getThreadName() + " " + r.getActiveThreads());
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Main");
in.close();
}
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
Thread t = new Thread(new Factorial());
t.start();
}
}
public synchronized void generate() {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
report.add(new Report(count--, Thread.currentThread().getName(), threadGroup.activeCount()));
notifyAll();
System.out.println("In generate" + threadGroup.activeCount());
}
#Override
public void run() {
generate();
synchronized (this) {
try {
wait();
}
catch(Exception e) {
e.printStackTrace();
}
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Run" + threadGroup.activeCount());
}
public static int getCount() {
return count;
}
public static void setCount(int count) {
Factorial.count = count;
}
}
Although I know that we can kill the threads using .stop() but I think it's not recommended.
To make synchronization effective (synchronized, wait, notify), you have to use the same instance.
In series, you create a new Factorial instance on each loop, making every thread to wait indefinitely.
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
// Thread t = new Thread(new Factorial()); // creates an new instance
Thread t = new Thread(this);
t.start();
}
}
In the run method, you first call notifyAll() (through generate), and then wait.
The last created thread will wait after all the others are done.
One way or another, this last thread has to be notified.
It could be right after the sleep call, with:
synchronized(f) {
f.notify();
}
or maybe with a dedicated synchronized method.
I'd like to implement my own semaphore in Java (just for practice, I am aware, that there is Semaphore class)
I have implemented it like that:
public class MySemaphore {
private int value = 1;
public synchronized void take() {
this.value++;
this.notify();
}
public synchronized void release(){
while (this.value == 0) {
try {
wait();
} catch (InterruptedException e) {
}
}
this.value--;
}
}
I am trying to use it in such thread:
public class MyThread extends Thread {
private static MySemaphore semaphore = new MySemaphore();
public void run(){
for (int i = 0; i < 100; i++) {
semaphore.take();
try {
Main.myVariable += 1;
semaphore.release();
} catch (Exception e){
System.out.println("Exception" + e.getMessage());
}
}
}
}
I start and join threads like this:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int myVariable = 0;
private static int threadsNumber = 100;
public static void main(String[] args) {
List<Thread> allThreads = new ArrayList<>();
for (int i = 0; i < threadsNumber; i++) {
allThreads.add(new Thread(new MyThread()));
}
for (int i = 0; i < threadsNumber; i++) {
allThreads.get(i).start();
}
for (int i = 0; i < threadsNumber; i++) {
try{
allThreads.get(i).join();
} catch (Exception e){
System.out.println(e.getMessage());
System.out.println("********************************");
}
}
System.out.println("Result is " + myVariable);
}
}
I just want to increment a variable 10000 times and receive a result. Without semaphore the result is less than 10000 (like 9923, 9684), which is caused by non-atomicity of incrementation. I want to protect this variable using semaphore.
Unfortunately, the result is still less than or equal to 10000 (but much closer, in 9 out of 10 cases greater than 9990).
Do you have any idea why it happens? Is my semaphore wrong or am doing something wrong with launching threads?
In your MySemaphore class, value is already set to 1. It should be zero because in your release function you are verifying if value equals zero or not. This means that when your program starts, no thread will be able to have the semaphore(because you have set it to 1); doing so, they fall into waiting state. Your program ends when 'threadsNumber' reaches it's limit.In other words, you are not verifying if any thread is in waiting state before the programs ends. This explains why you have a 9/10 as success rate.
My recommendation would be to try setting the value to zero and also verify if there are any threads in waiting state.
Your code be like this:
public class MySemaphore {
private int value = 0; //this is already an error in your code
public synchronized void take() {
this.value++;
this.notify(); // wakes up the first thread that called wait on the shared variable
}
public synchronized void release() throws InterruptedException{
while(this.signals == 0) wait();
this.value--;
}
}
I am looking at an example which code is:
class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
and
class TwoThreadsTest {
public static void main (String args[]) {
new SimpleThread("Jamaica").start();
new SimpleThread("Fiji").start();
}
}
My question is: is there a way each thread does its own code? For example, one thread increments a variable, while the other thread increments other variable.
Thanks.
P.S. Example's link is: http://www.cs.nccu.edu.tw/~linw/javadoc/tutorial/java/threads/simple.html
Each instance of SimpleThread has it's own local class storage. As long as you aren't using fields marked as static, then each thread will "do its own code". It is much harder to synchronize values between threads.
For example:
class SimpleThread extends Thread {
// this is local to an _instance_ of SimpleThread
private long sleepTotal;
public SimpleThread(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
long toSleep = Math.random() * 1000;
// add it to our per-thread local total
sleepTotal += toSleep;
sleep(toSleep);
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
Im new to Java and threads myself but you can do something like this (which may not be very efficient) but using an if statement to check the id or getName() of the thread and if it .equals the name of the particular thread then do this etc
so something like this:
int i;
int j;
if ("thread 2".equals(Thread.currentThread().getName())){
i++;
System.out.println("this is thread 2");
}
else {
j++;
...
}
This should allow you to make the threads run different tasks under the same run() method
i'm triyng to experiment the multithread programming (new for me) and i have some questions.
I'm using a ThreadPoolTaskExecutorwith a TestTask which implements Runnable and a run method wich sleeps for X seconds. Everyting went smoothly and all my TestTask were executed in a different thread. Ok.
Now the tricky part is that i want to know the result of an operation made in the thread. So i read some stuff on Google/stack/etc and i tried to use Future. And it's not working well anymore :/
I use the get method to get (oh really ?) the result of the call method and that part is working but the TestTask are executed one after another (and not at the same time like before). So i'm guessing i didn't understand properly something but i don't know what... and that's why i need your help !
The class wich launch test :
public void test(String test) {
int max = 5;
for (int i = 0; i < max; i++) {
TestThreadService.launch(i);
}
System.out.println("END");
}
The TestThreadService class :
public class TestThreadService {
private ThreadPoolTaskExecutor taskExecutor;
public void launch(int i) {
System.out.println("ThreadNumber : "+i);
taskExecutor.setWaitForTasksToCompleteOnShutdown(false);
TestTask testTask = new TestTask(i);
FutureTask<Integer> futureOne = new FutureTask<Integer>(testTask);
taskExecutor.submit(futureOne);
try {
Integer result = futureOne.get();
System.out.println("LAUNCH result : "+i+" - "+result);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setTaskExecutor(ThreadPoolTaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
}
And the TestTask Class :
public class TestTask implements Callable<Integer> {
public Integer threadNumber;
private Integer valeur;
public TestTask(int i) {
this.threadNumber = i;
}
public void setThreadNumber(Integer threadNumber) {
this.threadNumber = threadNumber;
}
#Override
public Integer call() throws Exception {
System.out.println("Thread start " + threadNumber);
// generate sleeping time
Random r = new Random();
valeur = 5000 + r.nextInt(15000 - 5000);
System.out.println("Thread pause " + threadNumber + " " + valeur);
try {
Thread.sleep(valeur);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread stop" + threadNumber);
return this.valeur;
}
}
I'm not bad in Java but this is the first time i'm trying to use different thread so i'ts kind a new for me.
What am i doing wrong ?
Thanks !
In your test method,
TestThreadService.launch(1);
should probably be
TestThreadService.launch(i);
Main thing though is the
Integer result = futureOne.get();
call in the launch method. Calling get() on a FutureTask is a blocking operation, meaning it will not return until the task is completed. That is why you are seeing a serial behavior. The use-case you are emulating (farming a bunch of activities and waiting for them to complete) is not one that the ThreadPoolTaskExecutor is ideally suited for. It does not have the "join" feature that raw threads have. That beeing said, what you want to do is something like
public Future<Integer> launch(int i) {
System.out.println("ThreadNumber : "+i);
taskExecutor.setWaitForTasksToCompleteOnShutdown(false);
TestTask testTask = new TestTask(i);
FutureTask<Integer> futureOne = new FutureTask<Integer>(testTask);
return taskExecutor.submit(futureOne);
}
And in your test method
public void test(String test) {
List<Future<Integer>> tasks = new ArrayList<Future<Integer>>();
int max = 5;
for (int i = 0; i < max; i++) {
tasks.add(TestThreadService.launch(i));
}
for (Future<Integer> task : tasks) {
System.out.println("LAUNCH result : " + task.get());
}
System.out.println("END");
}
also you can move setWaitForTasksToCompleteOnShutdown(false) into another method, for to dont be called each time you launch a thread, which is, as i see, (not very much threads), but in another scenario, with more tasks: an unnecessary and expensive job.
You can also create a public method on service, called: configure(); or, pre-launch(); before you start creating threads.
gluck!