Can this reference in run() refer to Thread object when implementing Runnable? - java

Sorry if the question is unclear
I am making a simple multithread program that has a linked list to store all thread created except the main thread. Then I want to send some signal to terminate the main thread but only when all other threads have closed and I intend to do this by making that when the thread close, it will remove itself from linked list then the main thread will check if that list size == null or not
here is my code
public class MainProgram {
//some global static variable
static List<Thread> threadList = new LinkedList<Thread>();
public void main() throws IOException {
ServerSocket serverSocket;
serverSocket = new ServerSocket(1234);
while(true){
if(Shutdown_Handler.shutdown==true){
//wait for all other thread close/terminate
return
}
Socket s = serverSocket.accept();
ClientThread x = new ClientThread(s);
Thread y = new Thread(x);
threadList.add(y);
y.start();
}
}
}
when Shutdown_Handler.shutdown==true the main will check the threadList if it is null. The problem is I don't know how to make the thread remove itself from the list. As what I have searched, for normal object, I can create method like this
public class someObject {
public static void delete(){
if(list.size = null) return;
list.remove(this);
}
}
However, in case of thread, the Class implement Runnable so this reference is to the object but not the thread stored in the list

I would recommend using a HashMap instead of a List. The keys can be the Thread Name (e.g. Thread.getName()) and the values will be the Threads.
Map<String, Thread> threadMap = new HashMap<String, Thread>();
You should also create this Map as a synchronizedMap (using Collections.synchronizedMap(...))
Map<String, Thread> synchronizedMap = Collections.synchronizedMap(threadMap);
Now, whenever you construct a Thread, you pass this HashMap into its constructor and the Thread can hold a reference to it. Therefore, when the Thread is about to terminate it can remove itself from the HashMap by using its own Thread name as the key to remove.

Assuming that ClientThread is a Runnable, the basic code is:
public class ClientThread implements Runnable {
public void run() {
// do stuff
MainProgram.threadList.remove(Thread.currentThread());
}
}
However this has a couple of problems:
There are going to be multiple threads performing operations on a list without proper synchronization. That is incorrect, and you are liable to get intermittent failures if you do this.
Unless run() removes the thread from the list in a finally block, a thread that terminates abnormally is liable to not get removed.
It is bad design to use a global static. And worse design to expose it as a bare (non-private) variable.
A HashSet<Thread> would be more efficient if the number of threads is liable to be large.

Related

Java Multithreading: Slow Producer and Fast Consumer

I'm trying to understand synchronized blocks. Here I have implemented a single producer thread and 2 consumer threads.
I keep getting exception in thread since LinkedList is empty.
package com.Main;
import com.qed.Consumer;
import com.qed.Producer;
import com.qed.Store;
public class Main {
public static void main(String[] args) throws InterruptedException {
Store st = new Store();
Thread populate = new Thread(new Producer(st));
Thread con1 = new Thread(new Consumer(st));
Thread con2 = new Thread(new Consumer(st));
con1.setName("A");
con2.setName("B");
populate.start();
con1.start();
con2.start();
populate.join();
con1.join();
con2.join();
if(populate.isAlive()){
con1.interrupt();
con2.interrupt();
}
}
}
package com.qed;
import java.util.LinkedList;
public class Store {
private LinkedList<Integer> qu = new LinkedList<Integer>();
private final Object lock = new Object();
public void add(int data){
try{
while(qu.size() ==10){
Thread.sleep(1);
}
qu.add(data);
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
public int remove(){
int data=0;
try{
synchronized(lock){
while(qu.size() == 0){
Thread.sleep(1);
}
data = qu.removeFirst();
}
}catch(InterruptedException ie){
ie.printStackTrace();
}
return data;
}
}
package com.qed;
public class Consumer implements Runnable{
private Store st;
public Consumer(Store st){
this.st=st;
}
public void run(){
while(true){
System.out.println(Thread.currentThread().getName() + ". " +st.remove());
}
}
}
package com.qed;
public class Producer implements Runnable{
private Store st;
private final int runs = 5000;
public Producer(Store st){
this.st = st;
}
public void run(){
int data = 0;
int curRun =0;
while(++curRun < runs){
st.add(data+=200);
}
System.out.println("DONE.");
}
}
Stack trace:
Exception in thread "B" Exception in thread "A"
java.util.NoSuchElementException
at java.util.LinkedList.removeFirst(Unknown Source)
at com.qed.Store.remove(Store.java:46)
at com.qed.Consumer.run(Consumer.java:20)
at java.lang.Thread.run(Unknown Source)
java.util.NoSuchElementException
at java.util.LinkedList.removeFirst(Unknown Source)
at com.qed.Store.remove(Store.java:46)
at com.qed.Consumer.run(Consumer.java:20)
at java.lang.Thread.run(Unknown Source)
You have to lock on adding as well. Your code allows a producer to update the queue while the consumer might want to remove an entry!
When two threads modify the same queue in parallel, all bets are off!
That single lock usage would only prevent multiple consumers to step on each other!
Thus: add the same kind of locking for the section that adds values.
Beyond that, EJP is correct - a real solution would make use of low level signaling methods such as wait() and notify(). But of course, using these would lead to a very different behavior.
And given your comment: keep in mind that these are TWO different things: A) consumer/producer sending signals to each other B) consumer/producing synchronizing on the same look.
I understand that you don't want "A)" - but you need "B)"; otherwise your queue gets corrupted, and surprises occur.
You should call wait() method here.
wait() makes your thread wait until some other thread calls notify to wake him up.
sleep() simply don't execute the next statement for specified time period.
And if you see your program snippet, you are using synchronize block which uses an object to check for the monitor availability. But you are not using any of the object monitor methods wait/notify/notifyAll and you're trying to acquire and release the lock without calling these methods. Since, list object used by both the consumer and producer you should use this list objects monitor to synch all the threads. If one thread acquired its monitor then other thread won't be able to access it. Because every object has only one monitor. This approach will solve the synchronisation issue among all the working threads.
Problem is your Store class implementation. Instead of sleeping, you need to implement a wait() and notify mechanism there while adding and removing elements.
You are correct in sharing a single Store instance among all consumers and producers but your store needs to behave like a BlockingQueue
So either you use an existing implementation of BlockingQueue from JDK or modify your Store class to implement similar mechanism.
implement-your-own blocking queue in java
Hope it helps !!

Creating and naming multiple, simultaneous threads with a for loop

Is there a way to create multiple threads that run simultaneously with a for loop? Consider this example:
for(int i = 1; i<=36; i++) {
if(new Random().nextInt(2)==0){
ActionThread nr = new ActionThread();
}
}
I don't want the threads to be killed after completion of the if statement. The end of each thread is randomly determined in the ActionThread class itself. Also, how do I name the threads automatically? For example, instead of nr, the first thread should be named nr1, the second nr2, the third nr3, and so on.
I'm assuming that ActionThread is some custom class that you have created that extends Thread.
I don't want the threads to be killed after completion of the if statement.
They won't be. However, it doesn't look like you have started them yet. Read the javadocs for Thread. Read the material at the top, then look at the start() and run() methods.
If you don't start a thread ... nothing happens.
Also, if you want some other part of your application to be able to "do things" to the threads once they have been created, you should replace the nr local variable with a data structure that the the rest of the application can get at; e.g. a list or an array.
(It is also possible to find extant threads via the ThreadGroup tree, but it is complicated.)
Also, how do I name the threads automatically?
Call Thread.setName(), or pass the thread name to the (relevant) Thread constructor. For example:
nr.setName("thr" + i);
Or you could even make your ActionThread set its own name in the constructor.
I should also point out that is is generally considered to be a bad idea to create subclasses of Thread. It is better to put your thread logic into a custom Runnable class, then create and pass a Runnable instance as a Thread construct argument. Like this:
public class MyRunnable implements Runnable {
#Override
public void run() {
// thread logic goes here
}
}
Thread th = new Thread(new MyRunnable());
th.start();
If you want to pass parameters to the thread logic, add a constructor to your runnable class with some arguments, and provide them when you instantiate the runnable.
Why do it this way? Because it allows you to easily change your code to use a thread loop or executor or some such.
public static void main(String[] a) {
List<ActionThread> threads = new ArrayList<>();
for (int i = 1; i <= 36; i++) {
if (new Random().nextInt(2) == 0) { // no idea why you have put this
// but seems unecessary
ActionThread thread = new ActionThread();
threads.add(thread);
thread.start();
}
}
}
class ActionThread extends Thread {
#Override
public void run() {
// Write what to do in Thread here
}
}
Once the list of ActionThread is there you have handle to all the Threads that you have created. using threads.get(index). From question its appears that by name you meant handle to Thread instance
For automatic naming, may be use static field (counter) in ActionThread and increment him in the constructor, before generate thread name.
class ActionThread extend Thread {
private static int id = 0;
ActionThread() {
setName(String.format("n%d", ++id);
}
}

Multiple threads working off the same list of strings, in java?

I'm trying to figure out the best way to have multiple threads working from the same list of strings. For example, say I have a list of words, and I want multiple threads to work on printing out each word on this list.
Here is what I came up with. The thread uses a while loop, and while the iterator has next, it prints out and removes it from the list.
import java.util.*;
public class ThreadsExample {
static Iterator it;
public static void main(String[] args) throws Exception {
ArrayList<String> list = new ArrayList<>();
list.add("comet");
list.add("planet");
list.add("moon");
list.add("star");
list.add("asteroid");
list.add("rocket");
list.add("spaceship");
list.add("solar");
list.add("quasar");
list.add("blackhole");
it = list.iterator();
//launch three threads
RunIt rit = new RunIt();
rit.runit();
rit.runit();
rit.runit();
}
}
class RunIt implements Runnable {
public void run()
{
while (ThreadsExample.it.hasNext()) {
//Print out and remove string from the list
System.out.println(ThreadsExample.it.next());
ThreadsExample.it.remove();
}
}
public void runit() {
Thread thread = new Thread(new RunIt());
thread.start();
}
}
This seems to work, although I get some Exception in thread "Thread-2" Exception in thread "Thread-0" java.lang.IllegalStateException errors during the run:
Exception in thread "Thread-1" Exception in thread "Thread-0"
java.lang.IllegalStateException at
java.util.ArrayList$Itr.remove(ArrayList.java:864) at
RunIt.run(ThreadsExample.java:44) at
java.lang.Thread.run(Thread.java:745) java.lang.IllegalStateException
at java.util.ArrayList$Itr.remove(ArrayList.java:864) at
RunIt.run(ThreadsExample.java:44) at
java.lang.Thread.run(Thread.java:745)
Am I doing this correctly or is there a better way to have multiple threads working on the same pool of strings?
A better way to do this is to use a concurrent queue. The Queue interface is designed to hold elements in a structure prior to processing them.
final Queue<String> queue = new ConcurrentLinkedQueue<String>();
queue.offer("asteroid");
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.execute(new Runnable() {
public void run() {
System.out.println(queue.poll());
}
});
executorService.shutdown();
Try creating the list as a synchronized list using List.synchronizedList
Update your code like this:
ArrayList<String> list = Collections.synchronizedList(new ArrayList<>());
Am I doing this correctly or is there a better way to have multiple threads working on the same pool of strings?
You are not doing it correctly. Your code is not properly synchronized, and therefore its behavior is not well defined. There are a great number of ways you could approach the general problem you present, but one way the issues in your particular code could be fixed would be to change RunIt.run() to properly synchronize:
public void run()
{
while (true) {
synchronized(ThreadsExample.it) {
if (ThreadsExample.it.hasNext()) {
//Print out and remove string from the list
System.out.println(ThreadsExample.it.next());
ThreadsExample.it.remove();
} else {
break;
}
}
}
}
Note here that the hasNext() check, retrieval of the next element, and removal of that element are all handled within the same synchronized block to ensure mutual consistency of these operations. On the other hand, the scope of that block is contained within the loop, so that different threads executing the loop concurrently each get a chance to execute.
Note, too, that although in this case all the threads synchronize on the Iterator object, that's basically just a convenience (for me). As long as they all synchronize on the same object, it doesn't matter so much which object that is.

Where do i have to use synchronized?

I have done some research and could not find a solution to this problem.
From this topic Synchronization, When to or not to use? i understand i could use synchronized, but doing so doesn't solve the problem.
The case is that i have a method in which a Thread is used to create an ArrayList. In that same Thread another method is called after a BufferedReader has finished reading a file and the lines are being added to the first List.
In the second method the first list is being used to create the second List. When all that is done, the first method uses the second list.
This is somewhat the code i use, if there is something not clear please ask and i will try to provide the info needed.
public synchronized void theBaseList() {
Thread t = new Thread() {
#override
public void run() {
try(
while((line = br.readLine()) != null) {
firstList.add(line):
}
}
nextMethod();
currentObject = (Object[]) secondList.get(0); // throws an exception
}
}
};
t.start();
public synchronized void nextMethod() {
Thread t1 = new Thread(){
double objectListSize = calculateObjectListLength(firstList.size());
#override
public void run() {
try {
// create Objects
secondList.add(objects);
}
}
};
t1.start();
}
When i use a Thread in nextMethod() to create a new list of Objects from the items in the first list, i get an ArrayIndexOutOfBoundsException saying
Exception in thread "Thread-4" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
I avoided this by not using a Thread in the second method and all works fine.
If i do use 2 Threads and make both methods synchronized, it still throws the exception.
Is it possible or should i just settle by not using a Thread in the second method? I thought synchronized was for dealing with this sort of problems. I don't understand why it doesn't work.
Let's say your methods are defined in a class named Sample and you've created an instance mySample. This appears to be what your code is doing:
main thread calls mySample.theBaseList() and synchronizes by locking on mySample.
theBaseList() defines thread1 and starts it.
theBaseList() exits scope, thus unlocking on mySample.
thread1 reads in the lines of a file and adds them to list1 (these operations are not synchronized)
thread1 calls mySample.nextMethod()
mySample.nextMethod() synchronizes by locking on mySample
nextMethod() defines thread2 and starts it.
nextMethod() exits scope, thus unlocking on mySample.
* thread2 sets up list2 (these operations are not synchronized)
* thread1, having returned from nextMethod() reads from list2 (these operations are not synchronized)
The last two operations are the cause of your race condition.
In your case, using synchronized methods is perhaps too coarse grained. A better option may be to synchronize on the object on which both threads operate, secondList.
nextMethod();
synchronized(secondList) {
currentObject = (Object[]) secondList.get(0); // should no longer throw an exception
}
synchronized(secondList) {
// create Objects
secondList.add(objects);
}
EDIT:
synchronized(secondList) {
nextMethod();
secondList.wait();
currentObject = (Object[]) secondList.get(0); // should no longer throw an exception
}
synchronized(secondList) {
// create Objects
secondList.add(objects);
secondList.notifyAll();
}

Multiple threads. Doing similar tasks, but need to see their output

I have a program which I select the amount of threads and it starts it, but I would like to have control of closing each thread one by one after they have started and see there output of each thread as well.
What is the best approach in this case?
These methods allow you to fetch results of all tasks, that were submitted to an executor service. And this shuts it down.
Create a Hashtable that will contain your threads and have the thread name used as the Key in the hashmap. So whenever you want to perform an operation on your thread you can get its reference from the hashtable and do whatever you want with it.
Hashtable<String, Thread> threadTable = new Hashtable<String, Thread>();
Thread t1 = new Thread() {
public void run() {
//Do sttuff
}
}
Thread t2 = new Thread() {
public void run() {
//Do sttuff
}
}
threadTable.put("T1", t1);
threadTable.put("T2", t2);
Of course this the above is just a simple example. If you take a class and make it extends Thread, you can then add methods to suspend and resume the thread as well as printing out its status.

Categories

Resources