I've a program that's as follows below. I want three concurrent threads to add different Strings to infiList ("This", "is", "infinite") using thread synchronization.
I want to append certain threads also, for example;
If the last word in infiList is currently “This”, the thread should append word “is” to infiList.
If the last word in infiList is currently “is”, the thread should append word “infinite” to infiList.
If the last word in infiList is currently “infinite”, or if infiList is still empty, the thread should append word “This” to infiList.
At any time, infiList should contain “This” only at the beginning of the list or directly after an occurrence of “infinite”, “is” should occur in the list only directly after a “This”, and an “infinite” should
occur only directly after an “is”.
Any help as to how to do this is appreciated.
import java.util.ArrayList;
public class Multithreading implements Runnable {
public static ArrayList<String> infiList = new ArrayList<>();
#Override
public void run() {
for (int i=0; i<100; i++) {
String s = null;
synchronized (infiList) {
if(infiList.isEmpty())
infiList.add("This");
else
{
s = infiList.get(infiList.size()-1);
if(s.equals("This"))
infiList.add("is");
else if(s.equals("is"))
infiList.add("infinite");
else if(s.equals("infinite"))
infiList.add("This");
}
}
}
}
public static void main (String args[]) {
// Create three concurrent threads
new Thread(new Multithreading()).start();
new Thread(new Multithreading()).start();
new Thread(new Multithreading()).start();
}
}
Very naive quick fix for the problem. Synchronized will obtain a lock, on the arraylist, check the element and insert it based on your rules. But due to your logic being depending on the last element while adding a element to the array while maintaning the order of the elements this is actually not multithreaded but a sequential program.
This is simply because, when multithreaded programs run, you don't care abount the sequentioning, because you can never guarentee it. In most cases you will go into a Divide and Conqueer style algorithm, where the algorithm will be split up into pieces and calculated in pieces.
#Override
public void run() {
for(int i = 0; i < 100; i++) {
String s = null;
synchronized (infiList) {
if(infiList.isEmpty())
infiList.add("This");
else
{
s = infiList.get(infiList.size()-1);
if(s.equals("This"))
infiList.add("is");
else if(s.equals("is"))
infiList.add("infinite");
else if(s.equals("infinite"))
infiList.add("This");
}
}
}
}
How to utilize multithreading
If we look at your example in another case, where you needed to calculate something before you put it into the array. This could lead to utilzing the multithreading performance better.
#Override
public void run() {
while (true) {
String s = null;
CalculateSomethingBig();
synchronized (infiList) {
...
}
}
}
If we play with the thought, that the primary runtime lies within CalculateSomethingBig(), this will now utilize more of the computers multitasking capabilities, because more of the threads will use time to calculate and utilize processing power then to wait on a lock being released.
How to get output
public static void main(String args[]) {
// Create three concurrent threads
new Thread(new Multithreading()).start();
new Thread(new Multithreading()).start();
new Thread(new Multithreading()).start();
for(String s : infiList)
System.out.println(s);
}
Related
I've got stuck in this question about multiple producers-consumers question. My goal is to write six threads to act as A, B,...,F, and let the program keep printing forever.
Please click here for the image:click
Each pair of nodes associated with an arrow correspond to a producers-consumers pair (or say buffer). The buffer size is 2 and initially, only A is in possession of 2 tokens.
I've already tried A -> B -> D ->F. The code is as below:
class Cookies
{
private int cookiesNo;
private int buffer=0;
public synchronized void put (int cNo, String sender, String receiver)
{
while (buffer==2)
{
try
{
wait();
}
catch (InterruptedException e){}
}
System.out.println(sender+" put the "+cNo+"th cookie to "+receiver);
cookiesNo= cNo;
buffer++;
notify();
}
public synchronized void eat (int cNo, String sender, String receiver)
{
while (buffer==0)
{
try {
wait();
}
catch (InterruptedException e){}
}
System.out.println(sender+" put the "+cNo+"th cookie to "+receiver);
cookiesNo= cNo;
buffer--;
notify();
}
}
class DPut implements Runnable
{
Cookies cookies;
DPut(Cookies cookies)
{
this.cookies=cookies;
}
public void run()
{
for (int i=1; i<=10000; i++)
{
cookies.put(i, "D", "F");
}
}
}
class DEat implements Runnable //human
{
Cookies cookies;
DEat(Cookies cookies)
{
this.cookies=cookies;
}
public void run()
{
for (int i=1; i<=10000; i++)
{
cookies.eat(i, "B", "D");
}
}
}
class APut implements Runnable
{
Cookies cookies;
APut(Cookies cookies)
{
this.cookies=cookies;
}
public void run()
{
for (int i=1; i<=100; i++)
{
cookies.put(i, "A", "B");
}
}
}
public class practice
{
public static void main(String[] args)
{
Cookies cookies= new Cookies();
DPut dput= new DPut(cookies);
DEat deat= new DEat(cookies);
APut aput= new APut(cookies);
Thread ddog= new Thread(deat);
Thread dmaster= new Thread(dput);
Thread amaster= new Thread(aput);
amaster.start();
ddog.start();
dmaster.start();
}
}
Output(I screenshot the beginning and the middle):
click1 click2
I tried to think it as master(producer), dog(consumer) and cookie(product). The master puts the cookie and the dog eats it.
My problems are:
The output looks like the first picture(AtoB & BtoD) in the beginning 100 cookies. Then it turned to picture two (BtoD & DtoF) until 10 thousand. How can I fix that? I want it to get AtoB running too, but it just stopped...
I don't know how to start on A and F, since they have two ins or two outs.
Is my strategy right? I wrote the code based on the single producer-consumer scenario.
I'm new to multi-threading so please tell me my mistakes.
Thank you so much!
First of all, although 'synchronized' is still valid for mutex, it is 15 years obsolete for signalling. If you want to do wait/notify, use reentrant locks and conditions await/signal[All].
Notify() only wakes 1 thread, and that maybe well be the wrong thread because you don't have any condition for the signal. The last put thread setting the buffer to 2 (full) might notify another put thread, then no more notify occurs to wake a eater.
The old way would be to use notifyAll(), and that would work although would wake up everyone and cause a lot of contention to acquire the synchronized for nothing except for one or two thread. That's why you should prefer reentrant lock with 2 conditions (not empty/notfull).
It's pretty much the basics behind an arrayblockingqueue.
I am new to concurrent programming and I am facing few issues with the below code using Java threads.
Status Class (this class tracks the position availability):
public class Status {
private static Map<String, Boolean> positions = new HashMap<>();
static {
//Initially all positions are free (so set to true)
positions.put("A", true);
positions.put("B", true);
}
public synchronized void occupyOrClear(String position,
boolean status) {
positions.put(position, status);
}
public boolean isClear(String position) {
return positions.get(position);
}
}
MyThread Class:
public class MyThread implements Runnable {
private String[] positions;
private String customer;
public MyThread(String customer, String[] positions) {
this.positions = positions;
this.customer = customer;
}
private Status status = new Status();
public void run() {
for (int i = 0; i < positions.length;) {
String position = positions[i];
if (status.isClear(position)) {
// position occupied now
status.occupyOrClear(position, false);
System.out.println(position + " occupied by :"+customer);
try {
//my real application logic goes below (instead of sleep)
Thread.sleep(2000);
} catch (InterruptedException inteExe) {
System.out.println(" Thread interrupted ");
}
// Now clear the position
status.occupyOrClear(position, true);
System.out.println(position + " finished & cleared by:"+customer);
i++;
} else {
try {
Thread.sleep(1000);
} catch (InterruptedException inteExe) {
System.out.println(" Thread interrupted ");
}
}
}
}
}
ThreadTest Class:
public class ThreadTest {
public static void main(String[] args) {
String[] positions = { "A", "B"};
Status status = new Status();
Thread customerThread1 = new Thread(new MyThread(status, "customer1", positions));
Thread customerThread2 = new Thread(new MyThread(status, "customer2", positions));
Thread customerThread3 = new Thread(new MyThread(status, "customer3", positions));
customerThread1.start();
customerThread2.start();
customerThread3.start();
}
}
Even though I have used 'synchronized' I could notice that some times Thread3 is picking up prior to Thread2 and could you please help me to resolve this issue and to acheive the following results ?
(1) Always customerThread1 should take the positions first and then
followed by customerThread2 and then customerThread3 (etc...)
(2) As soon as the A's position is freed by customerThread1, the
position should be immediately picked up by customerThread2 (rather
than customerThread2 and customerThread3 waiting till all positions
are done by customerThread1).And as soon as customerThread2 finishes
position 'A', then customerThread3 should pick it up, etc..
(3) As soon as the position (A, B, etc..) is freed/available, the next
customerThread should pick it up immediately.
(4) The solution should avoid all race conditions
There are several fundamental problems.
You have broken code and already noticed that it doesn’t work. But instead of asking how to fix that broken code, you are asking for alternatives with higher performance. You will never manage to write working programs with that attitude.
Apparently, you have no idea, what synchronized does. It acquires a lock on a particular object instance which can be held by one thread only. Therefore, all code fragments synchronizing on the same object are enforced to be executed ordered, with the necessary memory visibility. So your code fails for two reasons:
You are creating multiple instances of Status accessing the same objects referenced by a static variable. Since all threads use different locks, this access is entirely unsafe.
Your occupyOrClear is declared synchronized, but your method isClear is not. So even if all threads were using the same lock instance for occupyOrClear, the result of isClear remained unpredictable due to its unsafe access to the map.
You have code of the form
if(status.isClear(position)) { status.occupyOrClear(position, false); …
which matches the check-then-act anti-pattern. Even if each of these two method calls were thread-safe, this sequence still remained unsafe, because between these two invocations, everything can happen, most notably, the condition, the thread just checked, may change without the thread noticing. So two or more threads could invoke isClear, receiving true and then proceed with occupyOrClear.
You are using Thread.sleep.
You can try with the following pseudocode:
main() {
//some concurrent queues, eg ConcurrentLinkedQueue
Queue t1Tasks = new Queue("A","B","C");
Queue t2Tasks = new Queue();
Queue t3Tasks = new Queue();
Thread t1 = new PThread(t1Tasks,t2Tasks,"customer1");
Thread t2 = new PThread(t2Tasks,t3Tasks,"customer2");
Thread t3 = new PThread(t3Tasks,null,"customer3");
}
PThread {
Queue q1,q2;
PThread(Queue q1, Queue q2,...){}
run() {
while (item = q1.get()) {
//process item
q2.put(item); //to be processed by next thread
}
}
}
There is one ArrayList with 1 million element and we are using two threads to read from this ArrayList. The first thread will read first half of the list and second thread will read the second half of list and I am using two threads to achieve this, but I don't see any difference in performance between using one thread and two threads.
I have written below program to achieve this, but I am not sure If this is the right way to implement and achieve this.
Can someone check if my code is correct or how I can fix the multithreading?
import java.util.ArrayList;
import java.util.List;
public class ThreadTask {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
List<Integer> list = new ArrayList<>();
for(int i = 0; i <=1000000; i++){
list.add(i);
}
Thread t1 = new Thread(new PrintList(list));
Thread t2 = new Thread(new PrintList(list));
t1.setName("thread1");
t2.setName("thread2");
long starttime = System.currentTimeMillis();
System.out.println(starttime);
t1.start();
t2.start();
t1.join();
t2.join();
long endtime = System.currentTimeMillis();
System.out.println(endtime);
System.out.println("Total time "+(endtime - starttime));
}
}
class PrintList implements Runnable{
private List list = new ArrayList();
public PrintList(List list){
this.list = list;
}
#Override
public void run() {
if(Thread.currentThread().getName() != null && Thread.currentThread().getName().equalsIgnoreCase("thread1")){
for(int i = 0; i< list.size()/2;i++){
// System.out.println("Thread 1 "+list.get(i));
}
}else if(Thread.currentThread().getName() != null && Thread.currentThread().getName().equalsIgnoreCase("thread2")){
for(int i = list.size()/2; i<list.size(); i++){
//System.out.println("Thread 2 "+list.get(i));
}
}
}
}
Also, If someone can help me on how can we implement it to make it generic to use more then to thread.
System.out.println is synchronized internally (in order that you don't get mixing between the messages printed by multiple threads), so only one thread is actually printing at once.
Basically, it behaves like a single thread.
Even if in reality System.out is synchronized, still you dont want to have manually initialized threads reading from your ArrayList. Plus I doubt that your end goal is the System.out. You should use a higher abstraction. Such abstraction can easily be present either through Java8 Stream API either by ExecutorServices.
Here is one example of paralelism with Java 8 api.
Arraylist toprint;
toPrint.parallelstream().forEach(DoSometing);
This will work in parallel threads.
If you use ExecutorService You can slice your Arraylist and pass each slice to a Callable to perform the work for you in a separate thread.
class Task implements Callable {
List sublist;
public Task(List sublist) {
this.sublist = sublist;
}
public void call() {
// do something
}
}
ArrayList listToSlice;
List<List> slicedList;
ExecutorService executor = Executors.newFixedThreadPool(2);
for (List sublist:slicedList) {
Future<Integer> future = executor.submit(new Task(sublist));
......
.......s on
}
I'm having a difficult time understanding how to synchronise an ArrayList over two threads. Basically, I want one thread appending objects to the list and the other one reading from that list at the same time.
Here is the class that deploys the threads:
public class Main {
public static ArrayList<Good> goodList = new ArrayList();
public static void main(String[] args) {
Thread thread1 = new Thread(new GoodCreator());
Thread thread2 = new Thread(new WeightCounter());
thread1.start();
thread2.start();
}
}
Then the two Runnable classes:
This one reads lines of two values from a text file and appends new objects.
public class GoodCreator implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
private static Scanner scan;
#Override
public void run() {
System.out.println("Thread 1 started");
int objCount = 0;
try {
scan = new Scanner(new File(System.getProperty("user.home") + "//Goods.txt"));
} catch (FileNotFoundException e) {
System.out.println("File not found!");
e.printStackTrace();
}
while(scan.hasNextLine()){
String line = scan.nextLine();
String[] words = line.split("\\s+");
synchronized(goodList){
goodList.add(new Good(Integer.parseInt(words[0]), Integer.parseInt(words[1])));
objCount++;
}
if(objCount % 200 == 0) System.out.println("created " + objCount + " objects");
}
}
}
This iterates over the arraylist and is supposed to sum up one of the fields.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
No matter the input, weightSum never gets incremented and stays 0
Thread 1 started
Thread 2 started
0
Any help is much appreciated
You are running two independently running threads. These thread can run in any order and if one stop e.g. to read from a file, the other thread doesn't assume it has to wait for it.
In short, your second thread completes before the first thread has added anything to the list.
There is no good fix as this is not a good example of why you would use multiple threads, however to get an outcome what you can do is this.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
throw AssertionError(ie);
}
int weightSum = 0;
synchronized(goodList){
for (Good g : goodList)
weightSum += g.getWeight();
}
System.out.println(weightSum);
}
}
}
This will print the sum 10 times, 0.1 seconds apart. Depending on how long your file takes to load you will be able to see the sum for what has loaded so far.
This is something called a producer-consumer task. You can do it with arraylist, but it's honestly just not the right way to approach this problem.
Luckily, Java provides us with some collections, the BlockingQueue collections, which are designed specifically for this reason;
//the collection with the stuff in it
static BlockingQueue<Object> items = new BlockingQueue<Object>();
//(there are a few different types of blocking queues, check javadocs.
//you would want Linked or Array blocking queue
//what happens on the reader thread
public void producer()
{
//read the data into the collection
for (all the data in the file)
{
//add the next item
items.put(/* next item from file or w/e */);
//stop if necessary
if (atEndOfFile) stillReadingData = false;
//etc
}
}
Now you need to read the data out of the queue - luckily this is easy enough;
//what happens on the other threads
public void consumer()
{
//keep this thread alive so long as there is data to process
//or so long as there might be more data to process
while (stillReadingData || !items.isEmpty())
{
//get the next item from the list
//while the list is empty, we basically sleep for "timeout" timeunits,
//then the while-loop would repeat, and so on
Object o = items.poll(long timeout, int units);
if (o != null) //process it
}
}
In this way, you can continuously add items to the queue with the producer thread, and the items will be processed as soon as a consumer thread is free (this approach scales well with lots of consumer threads). If you still need a collection for the items, then you should make a second collection and add them to that after they have been processed.
As a side note, you may still need to synchronize oprations which occur while processing the items. For example, you would need to synchronize increments on "weightSum" (or alternately use AtomicInteger).
Try this change in the WeightCounter class.
public class WeightCounter implements Runnable{
private ArrayList<Good> goodList = Main.goodList;
#Override
public void run() {
System.out.println("Thread 2 started");
int weightSum = 0;
while(goodList.isEmpty()) {
Thread.sleep(1000);
}
synchronized(goodList){
for(Good g : goodList){
weightSum += g.getWeight();
}
}
System.out.println(weightSum);
}
}
This change will cause the WeightCounter thread to wait for the other thread to finish populating the goodList with data before attempting to read from it.
I have a method which takes a list and do some processing on it and it updates another global list. I need to run multiple instances of this method with different lists input in parallel.
Does multi-threading support this? If yes, how can i use it i.e.: what shall i put in the thread? Examples are highly appreciated.
I am thinking of having a static list in the thread class which gets updated by the different instances of the thread while running (the list contains strings and counters, so the update is adding new strings or increasing the counters of existing ones).. i need to read whatever gets added to this global list every 10 seconds and print it.. is using static list suitable for this and how can i make it thread safe?
Yes, that's a very common usage of multithreaded programming.
class ListProcessor implements Runnable {
/* field/s representing param/s */
public ListProcessor(/* param/s */) {
/* ... */
}
#Override
public void run() {
/* process list */
}
}
Then, when you want to actually process some lists.
class SomeClass {
ExecutorService listProcessor;
public SomeClass(/* ... */) {
listProcessor = ExecutorService.newFixedThreadPool(numThreads);
/* for each thread, however you want to do it */
listProcessor.execute(new ListProcessor(/* param/s */));
/* when finished adding threads */
listProcessor.shutdown();
/* note that the above two lines of code (execute/shutdown) can be
* placed anywhere in the code. I just put them in the constructor to
* facilitate this example.
*/
}
}
#purtip31 has a start for the parallel processing stuff.
I'm concerned about the results - you mention that you update a "global list". If multiple threads at a time are trying to update that list at the same time there could be problems. A couple of options:
Make sure that list is properly thread safe. This may or may not be easy - depends on exactly what is getting changed.
Use ExecutorService, but with the invokeAll() method, which runs a bunch of Callables in parallel and waits till they are all done. Then you can go through all of the results and update them one at a time. No threading issues with the results. This means that your code will have to implement Callable instead of Runnable (not a big deal). I have a blog with an example here
Well Sam...i m not much cleared with your question.....
try this out....
Following is a code which would help u to run mulitple instances.......
Main thread
public class mainprocess
{
public static LinkedList globallist;
public static String str;
public int num;
public static void main(String Data[])
{
globallist = new LinkedList();
// LinkedList will be passed as pass by reference.....
// globalist is made static and assigned likewise for global use..
childprocess.assignlist(globallist);
childprocess p1 = new childprocess("string input"); // a string input...
childprocess p2 = new childprocess(number input); // a number input...
p1.t.join();
p2.t.join();
}
}
The Child Thread.....
public class childprocess implements Runnable
{
public Thread t1,t2;
public boolean inttype,stringtype;
String string;
int num;
public static LinkedList temp = new Linkedlist();
public static assignlist(LinkedList ll)
{
temp = ll;
}
public childprocess(String str)
{
string = str;
t1 = new Thread(this,"stringThread");
t1.start();
}
#override
public childprocess(int n)
{
num = n;
t2 = new Thread(this,"numberThread");
t2.start();
}
#override
public void run()
{
// Both will be executed in a threader manner based on the condition...
if(Thread.currentThread().getName().equals("stringThread")
{
// your process using string......
childprocess.temp.add(str);
}
else if(Thread.currentThread().getName().equals("numberThread")
{
// your process using number.....
chilprocess.temp.add(num);
}
}
}
If you are using functions that should be restricted to only one thread at a time...
include the syntax....
public synchronized func_type func_name()
{
}