Now, I started to study Threading and decided to write this class to demonstrate the idea of Multi-Threading but the output wasn't what i want.
i wrote the class as follows : -
import java.util.LinkedList;
class QueueTest extends LinkedList{
int capacity;
LinkedList list;
public QueueTest(int capacity){
this.capacity = capacity;
list = new LinkedList();
}
public synchronized void addElements(int i)throws InterruptedException{
if(list.size() == capacity ){
wait();
}
add(i);
System.out.println("I added : "+i);
notify();
}
public synchronized int getElements() throws InterruptedException{
if(!isEmpty()){
wait();
}
int i = (Integer) list.remove();
System.out.println("I got : "+i);
notify();
return i;
}
}
class Add implements Runnable{
QueueTest t ;
public Add(QueueTest t){
this.t = t;
new Thread(this,"Add").start();
}
#Override
public void run(){
int i = 0;
while(t.size() <= t.capacity){
try{
t.addElements(i++);} catch(InterruptedException e){}
}
}
}
class Remove implements Runnable{
QueueTest t ;
public Remove(QueueTest t){
this.t = t;
new Thread(this,"Remove").start();
}
#Override
public void run(){
while(!t.isEmpty()){
try{
t.getElements();} catch(InterruptedException e){}
}
}
}
public class FullQueue{
public static void main(String[] args){
QueueTest t = new QueueTest(5);
new Add(t);
new Remove(t);
}
}
I expected the output to be like that
i added : 1
i got : 1
i added : 2
i got : 2
... and so on, but i got that output
I added : 0
I added : 1
I added : 2
I added : 3
I added : 4
I added : 5
Because the two threads are running at once there is no guarantee or control at all as to which runs when or in what order.
The get could run completely before the set, the set could run completely first, or they could run all mixed up.
An even interleaving like you display above is very unlikely to happen.
In that case the list has been filled fully by one thread, however the empty thread ran first and exited when it discovered there was nothing in the list.
Add diagnostics to show when each thread starts and ends and you should see that. The results will vary with every run though.
At the moment your notify does nothing as you have nothing waiting. To make the threads alternate then after each write or read you should notify and then wait. You would need to synchronize the whole block though and essentially you end up with a very complicated way to get the same result as one thread running.
this is loaded with race conditions. Note that the Remove thread will exit immediately if there are no elements.
Related
Okay so I have tested this code on java 8, 11, and 14, they all have the same result.
This is bad practice and an unrealistic scenario, but I would like to understand the JVM internals that causes this to happen.
If you run this code you will notice that everything except the print part itself of system.out.println inside if execute.
At some point with a slightly different java version I managed to get it to print by changing "play" too volatile, but even that doesn't work now.
Please at least test the code before claiming it is simply deadlocking the variables or using the cache, it is not, the if executes and everything inside it works except the print part itself.
public class Main {
public static void main(String[] args) {
TestClass t = new TestClass();
System.out.println("Starting test");
new MyRunnable(t).start();
while (true)
t.testUpdate(System.currentTimeMillis());
}
}
public class MyRunnable extends Thread {
private TestClass t;
public MyRunnable(TestClass t) {
this.t = t;
}
#Override
public void run() {
try {
Thread.sleep(500L);
t.setPlay(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TestClass {
private boolean play = false;
private long lastUpdate = 0;
private long updateRate = 2000;
private boolean hasSysoBeenHit = false;
public void testUpdate(long callTime) {
System.out.println(play);
System.out.println((callTime-lastUpdate));
if (this.play && ((callTime-lastUpdate) >= updateRate)) {
System.out.println("Updating! " + (hasSysoBeenHit = true));
this.lastUpdate = callTime;
}
System.out.println("hasbeenhit? " + hasSysoBeenHit);
}
public void setPlay(boolean t) {
System.out.println("Starting game...");
this.play = t;
}
}
Your code is suffering from a data race on the TestClass.play field: there are 2 threads accessing this field and at least one of them does a write. This is already indicated by #aerus.
If you make the field volatile, the data race gets removed. Look for the volatile variable rule in the Java Memory model.
I would also move the logic for the play checking to the begin of the testUpdate method:
public void testUpdate(long callTime) {
if(!play)return;
...
I've written a Multithreading code for producer consumer problem in which I've written synchronized block inside the run method of consumer and producer thread which takes lock on shared list(I assumed)
So the point of question is that, will there be locking on the list, because as per each thread will have their own synchronized block but they are sharing the same list instance
public class Main {
static boolean finishFlag=false;
final int queueSize = 20;
List<Integer> queue = new LinkedList<>();
Semaphore semaphoreForList = new Semaphore(queueSize);
public Main(int producerCount,int consumerCount) {
while(producerCount!=0) {
new MyProducer(queue,semaphoreForList,queueSize).start(); //produces the producer
producerCount--;
}
while(consumerCount!=0) {
new MyConsumer(queue,semaphoreForList,queueSize).start(); //produces the consumer
consumerCount--;
}
}
public static void main(String args[]) {
/*
* input is from command line 1st i/p is number of producer and 2nd i/p is number of consumer
*/
try {
Main newMain = new Main(Integer.parseInt(args[0]),Integer.parseInt(args[1]));
try {
Thread.sleep(30000);
}
catch(InterruptedException e) {
}
System.out.println("exit");
finishFlag=true;
}
catch(NumberFormatException e) {
System.out.println(e.getMessage());
}
}
}
class MyProducer extends Thread{
private List<Integer> queue;
Semaphore semaphoreForList;
int queueSize;
public MyProducer(List<Integer> queue, Semaphore semaphoreForList,int queueSize) {
this.queue = queue;
this.semaphoreForList = semaphoreForList;
this.queueSize = queueSize;
}
public void run() {
while(!Main.finishFlag) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) {
}
try {
if(semaphoreForList.availablePermits()==0) {//check if any space is left on queue to put the int
System.out.println("no more spaces left");
}
else {
synchronized(queue) {
semaphoreForList.acquire(); //acquire resource by putting int on the queue
int rand=(int)(Math.random()*10+1);
queue.add(rand);
System.out.println(rand+" was put on queue and now length is "+(queueSize-semaphoreForList.availablePermits()));
}
}
}
catch(InterruptedException m) {
System.out.println(m);
}
}
}
}
public class MyConsumer extends Thread{
private List<Integer> queue; //shared queue by consumer and producer
Semaphore semaphoreForList;
int queueSize;
public MyConsumer(List<Integer> queue, Semaphore semaphoreForList,int queueSize) {
this.queue = queue;
this.semaphoreForList = semaphoreForList;
this.queueSize = queueSize;
}
public void run() {
while(!Main.finishFlag) {//runs until finish flag is set to false by main
try {
Thread.sleep((int)(Math.random()*1000));//sleeps for random amount of time
}
catch(InterruptedException e) {
}
if((20-semaphoreForList.availablePermits())==0) {//checking if any int can be pulled from queue
System.out.println("no int on queue");
}
else {
synchronized(queue) {
int input=queue.remove(0);//releases the resource(position in queue) by pulling the int out of the queue and computing factorial
semaphoreForList.release();
int copyOfInput=input;
int fact=1;
while(copyOfInput!=0) {
fact = fact*copyOfInput;
copyOfInput--;
}
System.out.println(input+" was pulled out from queue and the computed factorial is "+fact+
" the remaining length of queue is "+(queueSize-semaphoreForList.availablePermits()));
}
}
}
}
}
I would rather recommend to use the java.lang.Object methods wait() and notify() to create a consumer-producer algorithm. Using this approach the queue won't be blocked by endlessly repeating and unnecessary synchronized statements which I think is a more performant and "event driven" solution.
This link might be helpful -
https://www.geeksforgeeks.org/producer-consumer-solution-using-threads-java/
Yes, the mutex/monitor is associated with the Java Object instance, which is the shared list in this instance. Which means all threads lock same mutex (associated with queue, and are synchronized through this.
So the good part: You program is actually thread-safe.
However the additional semaphore actually doesn't make a lot of sense in a variety of ways:
The checks (e.g. for availablePermits) happen outside of the lock, and are therefore only a best-guess about the state of your queue. It could be different shortly afterwards.
Trying to acquire a semaphore inside a lock, which can only be released inside the same lock, looks like a guaranteed recipe for a deadlock.
As AnDus has mentioned, this could probably be better solved via using the wait and notify methods which act as a condition variable. Most likely you need even two, one to unblock producers and one to unblock consumers.
In general, if this is not a coding exercise, use a class which already implements your desired functionality. In this case, java.util.concurrent.BlockingQueue seems like what you want.
If multiple threads are triggered does String variable (status) need to be synchronized?
class Request{
String status;
....// Some other variables used in thread
}
class Test{
public static void main(String[] args){
Requesr r = new Request();
List<Future> list= new ArrayList<Future>();
ExecutorService pool= Executors.newFixedThreadPool(10);
for(String input : inputList){
if(!"failed."equals(r.status)){
RequestHandler request = new RequestHandler(input,r);
Future f = pool.submit(request);
list.add(f);
}else{
//fail the job and return;
}
}
for (Future fTemp : list) {
if (fTemp.get() == null) {
// Task completed
}
}
}
}
class RequestHandler extends Runnable{
Map<String,String> input;
Requesr r;
RequestHandler(Map<String,String> input, Request r ){
this.input=input;
this.r = r;
}
#Override
public void run() {
if(!"failed".equals(r.status)){
try{
//some logic
}catch(Exception e){
r.Status = "failed";//status is assigned a value only here
}
}
}
}
Does status need to be synchronized for it to be visible in the Test class for loop and in other threads?
As mentioned below in comments I will use Future objects and cancel the running threads.
My doubt is whether above code works without synchronization logic. If it doesn't how can we add synchronization logic in this case?
The variable should probably be declared volatile. Else it may happen that a thread updates the value to "failed", but the main thread never sees this update. The reasons are explained here:
http://etutorials.org/Programming/Java+performance+tuning/Chapter+10.+Threading/10.6+Atomic+Access+and+Assignment/
It's possible (depending on what the triggering code does) that this is unnecessary, but it's not worth taking the risk.
I was asked to create my own thread pool in an interview where I have to create the number of threads requested by the user. Allow user to submit there task and finally shutdown the pool. I wrote the below program which is working fine in all the cases other than shutdown.
public class ThreadPool
{
public final Queue<Runnable> workerQueue;
private static boolean isrunning = true;
private Thread[] workerThreads;
public ThreadPool(int N)
{
workerQueue = new LinkedList<>();
workerThreads = new Thread[N];
for (int i = 0; i < N; i++) {
workerThreads[i] = new Worker("Pool Thread " + i);
workerThreads[i].start();
}
}
public void shutdown()
{
while(isrunning){
if(workerQueue.isEmpty()){
isrunning = false;
}
}
}
public void submit(Runnable r) throws Exception
{
workerQueue.add(r);
}
private class Worker extends Thread
{
public Worker(String name)
{
super(name);
}
public void run()
{
while (isrunning) {
try {
if(!workerQueue.isEmpty())
{
Runnable r = workerQueue.poll();
r.run();
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
}
}
The Test method I wrote is like below
static public void main(String[] args) throws Exception
{
ClassA a1 = new ClassA();
ClassA a2 = new ClassA();
ClassA a3 = new ClassA();
ClassA a4 = new ClassA();
ClassA a5 = new ClassA();
ClassA a6 = new ClassA();
ThreadPool tp = new ThreadPool(5);
tp.submit(a1);
tp.submit(a2);
tp.submit(a3);
tp.submit(a4);
tp.submit(a5);
///////////////
tp.submit(a6);
tp.shutdown();
}
But the program is never ending, its running always and I have to stop it manually in eclipse. But if I add a simple System.out.print("") in my method shutdown, its working perfrectly(the Program is ended after the execution of all the threads).
Can you please tell me why its working with the sysout and why its not working with out it ?
You have two major problems with your code:
You are using an implementation of Queue that's not synchronized in a multithread environment. This leads to a Race Condition when multiple threads insert/remove from the queue. Please consider using something like:
workerQueue = new ConcurrentLinkedQueue()
You run some very tight loops, one in your Worker.run() method where you're not checking for NPE and not allowing for some "cooldown", and another one in shutdown():
while (isrunning) {
...
Runnable r = workerQueue.poll();
r.run();
...
}
This, coupled with 1, leads to the Queue being emptied without properly updating the size info: ie. isEmpty() returns false but poll() returns null. Your program will become stuck in a loop. This doesn't happen when you add System.out.print() due to different timing specific to your configuration (it can continue to fail in other environments - especially where there are more than 6 cpu cores available).
I want to insert data with using JDBC.
I write this code :
//I want to start threads here
while(stmt_ver.next()){
stmt_ver.setString(i, "test"+... );
stmt_ver.executeBatch();
connection_ver.commit();
}
//I want to finish threads here
How can I do this with thread?
Here you go. Updated answer with code
Threaded class
public class MyThreadedClass extends Thread{
//Do what I need here on a thread
public void run(){
//Do what I need here
}
}
Main
//Main class
public static class MyProgramMain{
//Program main
public static void main(String[] args) {
//Send 10 threads
for (int i=0; i<10; i++){
//Init class (threaded)
MyThreadedClass threadedClass = new MyThreadedClass();
//Execute code in the class run() method
threadedClass.start();
}
}
}
Your question is hard to answer. You are asking very vague. Try to be clear. Post all necessary code. Try to explain what you did and what you would like to do.
Here is some hint for you. It will not run if you copy and past it, but I think it should make clear what you can try:
int i = 0;
while(i < columnCount ){
// make a new statement
Statement stmt_ver = new Statement();
// set your data and make the statement ready
stmt_ver.set...
// make a new thread that executes your data
// and let it run
new Thread(){
public void run(){
stmt_ver.addBatch();
stmt_ver.executeBatch();
connection_ver.commit();
}
}.start();
i++;
}
This is a very simple solution. It will start a thread it each iteration. Since I/O typically is taking some time, this could improve the execution time of your code. But be aware - threading is not easy. This is a very simple, naive solution. It could cause more problems than it solves. If you are not familiar with threads (and it seems like you are not) don't do it!
new Thread(new Runnable(){
#Override public void run(){
//enter code here
}
}).start();
EDIT You want to insert with many threads in parallel ...
There are many different possibilities.
You should read about: Concurrency (concurrent collections) and Executors.
EDIT 2 I agree with Thomas Uhrig , that introducing Threads could be more a harm than a blessing here.
Why do you think it would be helpful?
public class MockCommonDao {
ArrayList<ArrayList> listOlists = new ArrayList<ArrayList>();
public List CommonInsert(List<Object> example)
{
List<Future<Object>> listOlists = null;
ExecutorService executor = Executors.newFixedThreadPool(example.size());
List<TransactionImpl> callingList = new ArrayList<MockCommonDao.TransactionImpl>();
for (int i = 0; i < example.size(); i++) {
TransactionImpl localImpl = new TransactionImpl(example.get(i));
callingList.add(localImpl);
}
try {
listOlists = executor.invokeAll(callingList);
} catch (InterruptedException e) {
}
return listOlists;
}
private class TransactionImpl implements Callable<Object>{
private Object example;
TransactionImpl(Object Criteria) {
this.example = Criteria;
}
#Override
public Object call() throws Exception {
private class TransactionImpl implements Callable<Object>{
private Object example;
TransactionImpl(Object Criteria) {
this.example = Criteria;
}
#Override
public Object call() throws Exception {
while(stmt_ver.next()){
stmt_ver.setString(i, "test"+... );
stmt_ver.executeBatch();
connection_ver.commit();
}
}
}}
}
This code will make simualtaneous insert depending on value of your threads you want to create for insert.example.size() determines number of insert operations you want to perform.Hope you mean this.