#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2008
    Posts
    15
    Rep Power
    0

    Thread troubles


    Being new to threads, I'm finding it difficult to wrap my head around how to create separate instances of the same class being executed by multiple threads without those threads sharing any memory or data values except for ones I explicitly pass.

    For Example:
    java Code:
    decendants.add(tempLine);
    System.out.println(Thread.currentThread().getName() + " " + tempLine + " decendant#:" + decendants.size() + " gen:" + gens);
    SomeClass t = new SomeClass();
    t.Code = tempLine;
    t.decendants = decendants;
    t.maxGenHolders = maxGenHolders;
    System.out.println(gens);
    t.gens = gens + 1;
    System.out.println(gens);
    Thread thread1 = new Thread(t);
    sc.nextLine();
    thread1.start();


    All of the gens are sometimes output as different values. The two outputs in the center particularly frustrate me because they should be outputting the same value.
    Why does t.gens = gens + 1; modify gens in the current instance?

    Thankss!
  2. #2
  3. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    348
    Can you post the code for a small complete program that compiles, executes and shows the problem? The posted code can't be compiled and executed for testing.

    Also can you post the output from the program and explain what is wrong with the output and show what you expect the output to be.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2008
    Posts
    15
    Rep Power
    0
    Originally Posted by NormR
    Can you post the code for a small complete program that compiles, executes and shows the problem? The posted code can't be compiled and executed for testing.

    Also can you post the output from the program and explain what is wrong with the output and show what you expect the output to be.
    java Code:
    import java.net.*;
    import java.io.*;
    import java.util.*;
    import javax.swing.*;
    import java.awt.image.*;
    import javax.imageio.*;
    import java.awt.event.*;
    import java.awt.Color;
     
     
    public class CheckDecendantNumber implements ActionListener
    {
    	List<JLabel> labelList = new LinkedList();
    	JPanel panel1 = new JPanel();
    	JPanel panel2 = new JPanel();
    	JPanel panel3 = new JPanel();
    	JFrame frame;
    	JButton button = new JButton("Check Decendants");
    	JTextField textField = new JTextField(20);
    	File file;
    	BufferedImage img;
    	List<String> decendants = new LinkedList<String>();
    	int maxGen = 0, gens;
    	List<String> maxGenHolders = new LinkedList<String>();
     
    	public CheckDecendantNumber() throws Exception
    	{
    		frame = new JFrame("Decendant # checker");
    		java.awt.Container contentPane = frame.getContentPane();
    		panel1.add(textField);
    		panel1.add(button);
    		button.addActionListener(this);
    		contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.PAGE_AXIS));
    		frame.add(panel1);
    		frame.add(panel2);
    		frame.setVisible(true);
    		frame.pack();
    	}
    	public static void main(String[] args) throws Exception
    	{
    		CheckDecendantNumber app = new CheckDecendantNumber();
        }
    	public void actionPerformed(ActionEvent e)
    	{
    		if(e.getSource() == button)
    		{
    			try
    			{
    				DragonThread t = new DragonThread();
    				Thread thread1 = new Thread(t);
    				t.Code = textField.getText();
    				t.decendants = decendants;
    				t.maxGenHolders = maxGenHolders;
    				thread1.start();
     
    				System.out.println("Decendant count:" + decendants.size());
    				System.out.println("Largest Generation in lineage: " + maxGen);
    				System.out.println("Largest Generation Holders:");
    			}
    			catch(Exception err)
    			{
    				System.out.println(err);
    			}
    		}
    	}
    }
    class DragonThread implements Runnable
    {
    	String Code;
    	static int maxGen, gens;
    	static List<String> decendants;
    	static List<String> maxGenHolders;
    	public void run()
    	{
    		if (Thread.interrupted())
    		{
    			//We've been interrupted: no more crunching.
    		    return;
        	}
    		getChildren();
    	}
    	public void getChildren()
    	{
    		if(gens > maxGen-1)
    		{
    			maxGen = gens;
    			maxGenHolders.clear();
    		}
    		if(gens == maxGen)
    		{
    			maxGenHolders.add(Code);
    		}
    		try
    		{
    			String inputLine;
    			URL url = new URL("http://dragcave.net/progeny/" + Code);
    			BufferedReader in = new BufferedReader( new InputStreamReader( url.openStream()));
     
    			while ((inputLine = in.readLine()) != null)
    			{
    				Scanner sc = new Scanner(System.in);
    				//System.out.println(inputLine);
    				//sc.nextLine();
    				//System.out.println(inputLine);
    				if(inputLine.contains("<div class=\'d\'"))
    				{
    					inputLine = inputLine.substring(inputLine.indexOf("<div class=\'d\'"));
    					String tempLine = inputLine.substring(inputLine.indexOf("<a href"), inputLine.indexOf("</a>"));
    					tempLine = tempLine.substring(tempLine.indexOf("view/")+5, tempLine.indexOf("\">"));
    					if(!decendants.contains(tempLine) && !tempLine.equals(Code))
    					{
    						decendants.add(tempLine);
    						System.out.println(Thread.currentThread().getName() + " " + tempLine + " decendant#:" + decendants.size() + " gen:" + gens);
     
    						DragonThread t = new DragonThread();
    						Thread thread1 = new Thread(t);
     
    						t.Code = tempLine;
    						t.decendants = decendants;
    						t.maxGenHolders = maxGenHolders;
     
    						System.out.println(gens);//this prints out something different
    						t.gens = gens + 1;
    						System.out.println(gens);//than this
     
    						sc.nextLine();
    						thread1.run();//start();
    					}
    				}
    			}
    		}
    		catch(Exception e)
    		{
    			System.out.println("Retry!");
    			getChildren();
    			//e.printStackTrace();
    		}
    	}
    }

    My test case is "1JLm"

    Im expecting the output of gens to be the same number all 3 times. But it appears that gens in the current instance is being modified somehow.
  6. #4
  7. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    348
    it appears that gens in the current instance is being modified somehow.
    Can you post the program's output and add some comments to it explaining what is unexpected about it?
    Do you know what using the static attribute for a variable means?

    When I enter: 1JLm in the text field, this is displayed:
    Decendant count:0
    Largest Generation in lineage: 0
    Largest Generation Holders:
    Thread-2 kkEE decendant#:1 gen:0
    0
    1


    The program doesn't exit after displaying the above???
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2008
    Posts
    15
    Rep Power
    0
    Well I feel foolish now. While I was modifying the code I quickly added the gens declaration onto the end of another static variable. I guess all I needed was another set of eyes.... I suppose I should have just went to sleep instead of posting.

    And no the code doesn't exit after that section of output. I added in a scanner.nextLine() in order to see portions of output at a time. With that test case I provided, it would probably take a few hours to execute anyway.
    java Code:
    import java.net.*;
    import java.io.*;
    import java.util.*;
    import javax.swing.*;
    import java.awt.event.*;
     
     
    public class CheckDecendantNumber implements ActionListener
    {
    	List<JLabel> labelList = new LinkedList();
    	JPanel panel1 = new JPanel();
    	JPanel panel2 = new JPanel();
    	JPanel panel3 = new JPanel();
    	JFrame frame;
    	JButton button = new JButton("Check Decendants");
    	JTextField textField = new JTextField(20);
    	List<String> decendants = new LinkedList<String>();
    	int maxGen = 0, gens;
    	List<String> maxGenHolders = new LinkedList<String>();
     
    	public CheckDecendantNumber() throws Exception
    	{
    		frame = new JFrame("Decendant # checker");
    		java.awt.Container contentPane = frame.getContentPane();
    		panel1.add(textField);
    		panel1.add(button);
    		button.addActionListener(this);
    		contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.PAGE_AXIS));
    		frame.add(panel1);
    		frame.add(panel2);
    		frame.setVisible(true);
    		frame.pack();
    	}
    	public static void main(String[] args) throws Exception
    	{
    		CheckDecendantNumber app = new CheckDecendantNumber();
        }
    	public void actionPerformed(ActionEvent e)
    	{
    		if(e.getSource() == button)
    		{
    			try
    			{
    				DragonThread t = new DragonThread();
    				Thread thread1 = new Thread(t);
    				t.Code = textField.getText();
    				t.decendants = decendants;
    				t.maxGenHolders = maxGenHolders;
    				thread1.start();
     
    				System.out.println("Decendant count:" + decendants.size());
    				System.out.println("Largest Generation in lineage: " + maxGen);
    				System.out.println("Largest Generation Holders:");
    			}
    			catch(Exception err)
    			{
    				System.out.println(err);
    			}
    		}
    	}
    }
    class DragonThread implements Runnable
    {
    	String Code;
    	static int maxGen;
    	int gens;
    	static List<String> decendants;
    	static List<String> maxGenHolders;
    	public void run()
    	{
    		if (Thread.interrupted())
    		{
    			//We've been interrupted: no more crunching.
    		    return;
        	}
    		getChildren();
    	}
    	public void getChildren()
    	{
    		if(gens > maxGen-1)
    		{
    			maxGen = gens;
    			maxGenHolders.clear();
    		}
    		if(gens == maxGen)
    		{
    			maxGenHolders.add(Code);
    		}
    		try
    		{
    			String inputLine;
    			URL url = new URL("http://dragcave.net/progeny/" + Code);
    			BufferedReader in = new BufferedReader( new InputStreamReader( url.openStream()));
     
    			while ((inputLine = in.readLine()) != null)
    			{
    				Scanner sc = new Scanner(System.in);
    				//System.out.println(inputLine);
    				//sc.nextLine();
    				//System.out.println(inputLine);
    				if(inputLine.contains("<div class=\'d\'"))
    				{
    					inputLine = inputLine.substring(inputLine.indexOf("<div class=\'d\'"));
    					String tempLine = inputLine.substring(inputLine.indexOf("<a href"), inputLine.indexOf("</a>"));
    					tempLine = tempLine.substring(tempLine.indexOf("view/")+5, tempLine.indexOf("\">"));
    					if(!decendants.contains(tempLine) && !tempLine.equals(Code))
    					{
    						decendants.add(tempLine);
    						System.out.println(Thread.currentThread().getName() + " " + tempLine + " decendant#:" + decendants.size() + " gen:" + gens);
     
    						DragonThread t = new DragonThread();
    						Thread thread1 = new Thread(t);
     
    						t.Code = tempLine;
    						t.decendants = decendants;
    						t.maxGenHolders = maxGenHolders;
     
    						t.gens = gens + 1;
     
    						sc.nextLine();
    						thread1.run();
    					}
    				}
    			}
    		}
    		catch(Exception e)
    		{
    			System.out.println("Retry!");
    			getChildren();
    			//e.printStackTrace();
    		}
    	}
    }


    I'm still experiencing trouble with the gens variable being correctly computed during thread execution.

    While the run method is being called without the use of threads as in the code above (line 121), it is 100% correct. However when changed to .start(), different values are displayed.

    This is obviously a thread issue and something I'm overlooking like synchronized or something. But it is not obvious as to why different values are found. Each thread should be dealing only with its respective instance and the threads that it is creating. Nothing should be modifying the same values at the same time.

    It should be acting like a tree. Say for example, you have a tree of nodes. I want to traverse the nodes from top to bottom using threads.

    My goal is to send in a node, and create a thread for each child node.

    Edit: Actually... I think I got it. The first generation can see the third generation and its possible for thread-x to get there before thread-y.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2008
    Posts
    15
    Rep Power
    0
    Say you had class with a static list of ints and an instance dependant variable.
    A method in this class recursively creates threads of the same object in a loop.
    Each thread adds an int to the static list and prints the size of the list.
    The instance dependant variable is needed to keep track of where in the tree the current thread is.

    java Code:
    import java.util.*;
     
    public class test
    {
    	public static void main(String args[])
    	{
    		one t = new one();
    		Thread thread = new Thread(t);
    		thread.start();
    	}
    }
    class one implements Runnable
    {
    	static List<Integer> number = new LinkedList();
    	int instanceData;
     
    	public void run()
    	{
    		count();
    	}
    	public synchronized void count()
    	{
    		while(true)
    		{
    			one t = new one();
    			Thread thread = new Thread(t);
    			t.instanceData = instance data + 1;
    			number.add(0);
    			System.out.println(number.size() + " leaf # " + instance data);
    			thread.start();
    		}
    	}
    }


    Is there any way to synchronize separate instances?
    Is there any way to keep track of data with threads without instances?
    Or is there a better method that will make this work?
  12. #7
  13. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,711
    Rep Power
    348
    The posted code has compiler errors. Can you post the current version of your working program so it can be compiled and executed for testing?


    What is the posted code supposed to do?
    The while(true) loop will execute forever until you use up all memory.
    Last edited by NormR; January 3rd, 2013 at 09:36 AM.

IMN logo majestic logo threadwatch logo seochat tools logo