Toon posts:

[java] Functie meermaals aanroepen

Pagina: 1
Acties:
  • 104 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Hallo,

Ik heb een vraagje over threads en hopelijk kunnen jullie mij hierbij helpen.
Dit voorbeeldje heb ik van het internet:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class PrintChar extends Thread {
    private char charToPrint;
    private int times;
    Thread myThread;
    private boolean frozen = true;
    //Contruct thread to print ii++
    public PrintChar(char charToPrint,int times){
        this.charToPrint = charToPrint;
        this.times = times;
/*      for(int n=0;n <=times;n++){
            System.out.print(charToPrint); 
        }*/
    }

    public void run(){
    for(int n=0;n <=times;n++){
        System.out.print(charToPrint);
        yield();//pause for other thread

//      try {
//                sleep((int)(Math.random() * 1));
//            } catch (InterruptedException e) {}
        }

    }
}
public class TestThread {
    //main method
    public static void main(String[] opt) {

        //create object+threads
        StopWatch tijd = new StopWatch();
        PrintChar printA = new PrintChar('a', 58);
        PrintChar printB = new PrintChar('b', 50);
        //PrintChar printC = new PrintChar('c', 25);
        //PrintNum print666 = new PrintNum(60);
        //PrintNum print667 = new PrintNum(90);

        //Sstart treads
        tijd.beginTime();
        printA.start();
        printB.start();
        //printC.start();
        //print666.start();
        //print667.start(); 
        tijd.stopTime();        
        tijd.diffTime();                                                          
  }
}                               


Simpel voorbeeldje, het print "a en b " n keer.

output: ababab....................

ok, nou wil ik het volgende:
In de PrintChar functie de forloop zetten die nou in de run functie zit en de PrintChar
aanroepen in run, zoals hieronder:
Java:
1
2
3
4
5
6
7
8
9
10
11
 public PrintChar(char charToPrint,int times){
        this.charToPrint = charToPrint;
        this.times = times;
/*      for(int n=0;n <=times;n++){
            System.out.print(charToPrint); 
        }*/
    }

    public void run(){
          PrintChar(charToPrint, times);
        yield();//pause for other thread


Is dit mogelijk? zoja, hoe doe ik dit?

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 23-03 10:29

NetForce1

(inspiratie == 0) -> true

Waarom zou je dat überhaupt willen? Een thread 'leeft' zolang de run-method gestart en nog niet beeindigd is, de run-methode is dus de aangewezen plek om dit soort dingen te doen. Wellicht dat het handig is om de javadoc van Thread en Runnable er eens op na te slaan.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • zwippie
  • Registratie: Mei 2003
  • Niet online

zwippie

Electrons at work

Wat jij de PrintChar functie noemt is eigenlijk de constructor van de klasse PrintChar. Een constructor wordt maar 1 keer aangeroepen tijdens de levensduur van een object, dus de code in de constructor wordt ook maar 1 keer aangeroepen.
Verder, wat je in je onderste run methode voorstelt klopt ook niet echt lijkt me. Je maakt daar namelijk weer een nieuw PrintChar object dat verder nergens wordt gebruikt.

Volgens mij ben je threads nu al ontzettend aan het misbruiken.
Als je een loopje wil maken om karakters te printen heb je geen threads nodig. Als je het met een interval zou willen doen wel, maar dan zou ik je daar eerst nog eens wat meer in verdiepen.
(no flame intended, threads kunnen best lastig zijn)

How much can you compute with the "ultimate laptop" with 1 kg of mass and 1 liter of volume? Answer: not more than 10^51 operations per second on not more than 10^32 bits.


  • .daan
  • Registratie: Januari 2002
  • Laatst online: 23-09-2023

.daan

{visibility:hidden;}

Het zou handig zijn om te weten wat je precies wilt met dit programma. Als het puur gaat om het printen van n tekens lijkt een Thread niet echt de goede manier hiervoor, zoals zwippie ook al aangeeft. Maar zonder het doel van het programma te kennen is daar moeilijk over te oordelen natuurlijk.

[ Voor 28% gewijzigd door .daan op 14-01-2006 17:39 ]

public void ik()


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-04 03:50
De code van de constructor van je thread-object draait gewoon in de oorspronkelijke thread-context. Als je iets in een aparte thread wil doen moet je het dus juist in de run() methode doen. Sowieso is het netjes om je in de constructor van te beperken tot initialisatie van het object en het gedrag van het object zelf (zoals het printen van tekst) in methodes te zetten.

Verder ben ik het met de mensen boven mij eens: het is handig om te weten waar je nu precies naar toe wilt, want uit je voorbeeldcode blijkt niet wat je doel is of dat je ueberhaupt veel verstand hebt van OO-programmeren of multithreaded code.

Verwijderd

Topicstarter
Ik zal even vertellen waar ik mee bezig ben. 2maanden geleden ben ik begonnen om software te maken dat een muis laat bewegen via je hoofdbewegingen met een wabcam. Nou gebruik ik een headtracker, maar die werkt alleen onder windows.

Nou ben ik begonnen met een programmatje te maken die een foto van mijn hoofd laad, daarna zoekt hij naar een kernmerk(in dit geval een witte stip) en filtert de rest weg

code:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import java.lang.Thread;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.imageio.stream.*;

class Image extends Thread{
  protected int width;
  protected int height;
  protected int[][] samples;
  protected int[][] samples2;
  public int status = 0 ; //status 1/0
  private int[][] selectedArray;//samples2||samples
  String filename;
  private int imageLoaded = 0;

  public Image(String filename) throws Exception { //Default
//  public Image() throws Exception { //Default
    // super(filename);
    System.out.println(status+ ","+ imageLoaded); //laat zien of foto geladen is 1
    read(filename);
    System.out.println(status+ ","+ imageLoaded);
    threshold(239);
      //flipBits();
    }

  public int getWidth() {
    return width;
  }

  public int getHeight() {
    return height;
  }

  public void read(String filename) throws Exception { //Read file, file pixel set into samples[][]
    String filenameExtension = filename.substring(filename.indexOf('.')+1);
    File fileImage = new File(filename);
    Iterator imageReaders = ImageIO.getImageReadersBySuffix(filenameExtension);
    ImageReader imageReader;
    if (imageReaders.hasNext()) imageReader = (ImageReader)imageReaders.next();
    else throw new IIOException("Unsupported image format");
    FileImageInputStream imageInputStream = new FileImageInputStream(fileImage);
    imageReader.setInput(imageInputStream);
    width = imageReader.getWidth(0);
    height = imageReader.getHeight(0);
    BufferedImage bufImage = imageReader.read(0);
    imageInputStream.close();
    WritableRaster wRaster = bufImage.getRaster();
    int numBands = wRaster.getNumBands();
    if(status == 0){
        samples = new int[height][width];
        selectedArray = samples;
//      switchStatus();
    }
    else{
        samples2 = new int[height][width];
        selectedArray = samples2;
//      switchStatus();
    }
    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
          selectedArray[row][col] = wRaster.getSample(col,row,0);
//  createMatrix();
//  copyArraytoArray();
        }
    }
    imageLoaded = 1;
    
  }

  
  public void draw(Graphics gc,int x,int y) {//Create buffered and draw
    BufferedImage bufImage = createBufferedImage();
    gc.drawImage(bufImage,x,y,null);
  }

  public void update(Graphics g){
//    draw(
  }

  
    public void writeArraytoFile(String saveFile){// Write pixel value to file
        try {
            FileWriter outFile = new FileWriter(saveFile);
            PrintWriter out = new PrintWriter(outFile);
            // Write color(dot) value to file
            if(status == 0)
                selectedArray = samples;
            else
                selectedArray = samples2;
            for(int row = 0; row<height;row++){
                for(int col = 0; col<width;col++){
                    int s = selectedArray[row][col];            
                    if(s > 239) 
                        out.print(s +"*,");
                    out.print(s +","); //else
                }
                out.println("New Line");
            }
            out.close();
            }
            catch (IOException e){
                e.printStackTrace();
            }
    }   

  public void flipBits() { //Convert from W/B &R B/W
      if(status == 0)
          selectedArray = samples;
      else
          selectedArray = samples2;
      for (int row = 0; row < height; row++) {
          for (int col = 0; col < width; col++) {
              if(selectedArray[row][col] >1) {
                  selectedArray[row][col] = 0;
              }
              else {
               selectedArray[row][col] = 255;
           }
      }
    }    
  }
  public void threshold(int x) { // pixel > value x =black
      if(status == 0)
          selectedArray = samples;
      else
          selectedArray = samples2;
      for (int row = 0; row < height; row++) {
         for (int col = 0; col < width; col++) {
             if (selectedArray[row][col] < x) {
                 selectedArray[row][col] = 0;
             }    
             else {
                 selectedArray[row][col] = 255;
             }
         }
     }
   imageLoaded = 0;
  }

    public void switchStatus(){ 
        if(status>0){
            status = 0;
        }
        else{
            status = 1; //else
        }
    }

    public void run(){
        switchStatus();
//      if(status == 1)
            
//      {
            
//          read(filename);
//          System.out.println("status:" +imageLoaded);
    //      status = 1;
            yield();
//      }
//      update(gc);
//      System.out.println("Image is unloaded");
        //  yield();
/*      
        try{
            read(filename);
            filterAll();
        }   
        catch (Exception e) {
            System.out.println("Exception in main() "+e.toString());
        }
*/
    }
    
    private BufferedImage createBufferedImage() {
      if(status == 0)
          selectedArray = samples;
      else
          selectedArray = samples2;
        BufferedImage bufImage = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);//Convert to Gray 8 bit
        WritableRaster wRaster = bufImage.getRaster();
        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                wRaster.setSample(col,row,0,selectedArray[row][col]);
            }
        }
        return bufImage;
    }
}

Even terug komen op de vraag, ik wil dat wanneer foto1 aan het filteren is er een 2e thread wordt gemaakt om een 2e foto te laden.

Ter illustratie:

read --------------- filter
......................... read -----------------filter
..................................................... read----------------- filter
Ookwel doublebuffering genoemd.

Hoe kan ik dit het best inpementeren?

[ Voor 4% gewijzigd door Verwijderd op 17-01-2006 20:16 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-04 03:50
Threads zijn hier inderdaad de goede oplossing voor. Ik kan me al twee mogelijke scenario's indenken. Ten eerste kun je een aparte thread hebben om plaatjes te laden en een aparte thread om ze te filteren. De read-thread stopt ze in een queue en de filter-thread haalt ze er uit. Dit is min ofmeer het scenario dat jij voorstelt.

Een alternatief (en misschien logischer) scenario is dat waarin je het lezen en filteren van een plaatje als een enkele 'job' ziet. Dit gaat er vanuit dat er geen relatie zit tussen de plaatjes (je hebt de resultaten van eerdere jobs niet nodig voor volgende jobs). Je kunt dan gewoon een willekeurig aantal jobs tegelijk starten in aparte threads.

In beide scenarios kun je een semaphore (zie java.util.concurrent.Semaphore, sinds Java 1.5) gebruiken om de grootte van de queue of het aantal concurrente jobs te beperken.

Het tweede scenario is naar mijn mening simpeler en robuuster, omdat er geen data-afhankelijkheden tussen threads zijn zoals wel in het eerste scenario het geval is.

Verwijderd

Topicstarter
Soultaker schreef op zondag 15 januari 2006 @ 22:03:
Threads zijn hier inderdaad de goede oplossing voor. Ik kan me al twee mogelijke scenario's indenken. Ten eerste kun je een aparte thread hebben om plaatjes te laden en een aparte thread om ze te filteren. De read-thread stopt ze in een queue en de filter-thread haalt ze er uit. Dit is min ofmeer het scenario dat jij voorstelt.

Een alternatief (en misschien logischer) scenario is dat waarin je het lezen en filteren van een plaatje als een enkele 'job' ziet. Dit gaat er vanuit dat er geen relatie zit tussen de plaatjes (je hebt de resultaten van eerdere jobs niet nodig voor volgende jobs). Je kunt dan gewoon een willekeurig aantal jobs tegelijk starten in aparte threads.

In beide scenarios kun je een semaphore (zie java.util.concurrent.Semaphore, sinds Java 1.5) gebruiken om de grootte van de queue of het aantal concurrente jobs te beperken.

Het tweede scenario is naar mijn mening simpeler en robuuster, omdat er geen data-afhankelijkheden tussen threads zijn zoals wel in het eerste scenario het geval is.
Bedankt voor de 2e scenario.

Ik zou terug wllen naar de 1e post. Dit is mijn eerste echte programma die ik maakt, ik kan de basis wel, maar ik heb niet veel praktijk gedaan.

Ik denk dat ik een verkeerd beeld heb van threads. Zelf dacht ik om het volgende te doen:

code:
1
2
3
4
5
  public Image(String filename) throws Exception { //Default
    read(filename); // methode om foto te laden
    threshold(239);// filter methode
    flipBits();// filter methode
    }

Dit beschouw ik als een 'job'.

Als ik nou deze 'job methode' in de run() zou zetten, dan dacht ik dat een thread werd.
Verkeerd gedacht.

  • zwippie
  • Registratie: Mei 2003
  • Niet online

zwippie

Electrons at work

Verwijderd schreef op maandag 16 januari 2006 @ 14:51:
[...]
Als ik nou deze 'job methode' in de run() zou zetten, dan dacht ik dat een thread werd.
Verkeerd gedacht.
Niet zo verkeerd hoor, het klopt bijna wat je zegt.
Je maakt een klasse die Thread extend, of eentje die Runnable implementeert. In die klasse moet een run methode staan, de code in deze methode wordt in een aparte thread-context uitgevoerd. Het aanroepen van deze methode doe je met start().
Je 'job' komt dus zeker wel in run() te staan. :)

De links die NetForce1 gaf plus de Threads Tutorial zijn echt verplicht leesvoer.

How much can you compute with the "ultimate laptop" with 1 kg of mass and 1 liter of volume? Answer: not more than 10^51 operations per second on not more than 10^32 bits.


  • NetForce1
  • Registratie: November 2001
  • Laatst online: 23-03 10:29

NetForce1

(inspiratie == 0) -> true

zwippie schreef op maandag 16 januari 2006 @ 16:02:
[...]

De links die NetForce1 gaf plus de Threads Tutorial zijn echt verplicht leesvoer.
En als je meer met threads wilt doen is dit boek ook zeker een aanrader!

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Verwijderd

Topicstarter
zwippie schreef op maandag 16 januari 2006 @ 16:02:
[...]


Niet zo verkeerd hoor, het klopt bijna wat je zegt.
Je maakt een klasse die Thread extend, of eentje die Runnable implementeert. In die klasse moet een run methode staan, de code in deze methode wordt in een aparte thread-context uitgevoerd. Het aanroepen van deze methode doe je met start().
Je 'job' komt dus zeker wel in run() te staan. :)

De links die NetForce1 gaf plus de Threads Tutorial zijn echt verplicht leesvoer.
Ik heb de java tut over threads gelezen en ik snap het nog niet.

Op dit moment heb ik een testimage class:
hierin staat:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.awt.*;
import javax.imageio.*;
import java.io.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
//import 
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
    
class TestImage extends JPanel{
    String image = "test.gif";
  public static void main(String args[]) throws Exception {
      StopWatch tijd = new StopWatch();
//    GUI gui = new GUI();
      //GUI
      JFrame f = new JFrame("TestImage");
      f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {
          System.exit(0);
      }
      });
      f.setContentPane(new TestImage());
      f.pack();
      f.setVisible(true);
      f.setExtendedState(JFrame.MAXIMIZED_BOTH); //Maximizes frame 

//    gui.buildFrame();
//    tijd.start();
//    JFrame gu = new JFrame();

// gu.setContentPane(new TestImage());
      Graphics gc = f.getGraphics();    
    try {
        int x = 0;
        int y = 300;
        tijd.start();
      // Read the image
        String[] files= {"1.jpg","2.jpg","3.jpg","4.jpg"};
        for(int i=0;i<4;i++){
        System.out.println("Loading image");
        Image img = new Image();
                img.read(files[0]); 
        System.out.println("Image loaded");
        int width = img.getWidth();
        int heigth = img.getHeight();
        // Display the image
        img.draw(gc,x,0);
        System.out.println("Image drawed");
        img.threshold(240);
        img.flipBits();
//      img.filterAll();
//      img.write("thresholdWholeImage.jpg");
        System.out.println("Filtering done");
//      img.writeArraytoFile("threshold.txt");
//      start = start+5;
        // Write the new image to a file
        //img.write("Threshold4.jpg");
        img.draw(gc,x,y);
        x = x + width;
        } 
        }
    catch (Exception e) {
      System.out.println
     ("Exception in main() "+e.toString());
    }

  tijd.stop();
  tijd.verschil();
  }
}


TestImage laadt 5 foto's, filterd ze, en laat ze zien. Als ik het goed begrijp, moet ik 2 klasses (laadFoto.java, filterFoto.java)maken met een threads extends.
In laadFoto.java moet run functie met de inhoud van read() van mijn Image klasse en in filterFoto een run functie met de inhoud van die filter methodes van Image.java?

Begrijp ik dit goed.

[ Voor 4% gewijzigd door Verwijderd op 17-01-2006 20:13 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-04 03:50
Het tweede scenario dat ik noemde was anders. Daarvoor maak je een klasse die deze code uitvoert (het laden én het filteren) voor een bepaald bestand. Opzetje:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class ImageProcessor extends Thread
{
    public final string inputFilename, outputFilename;
    private boolean succeeded;

    public ImageProcessor(string in, string out)  {
        inputFilename  = in;
        outputFilename = out;
    }

    public static void run() {
        try {
            Image img = new Image();
            img.read(inputFilename);
            // ... en hier ook je filter code
            img.write(outputFilename);
            succeeded = true;
        } catch(Exception e) {
            // Exception printen, of iets dergelijks
            succeeded = false;
        }
    }

    public boolean succeeded() {
        return succeeded;
    }
}


Zo'n object instantieer je dan met de bestandsnamen van het invoer- en uitvoerbestand en vervolgens kun je 'm uitvoeren. De code in de main class ziet er dan zo uit:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String[] input   = {"in1.jpg", "in2.jpg", ... };
String[] output = {"out1.jpg", "out2.jpg", ... };
ImageProcessor[] threads = new ImageProcessor[input.size()];
for(int n = 0; n < input.size(); ++n) {
    threads[n] = new ImageProcessor(input[n], output[n]);
    threads[n].start(); // nu wordt threads[n].run() aangeroepen in een aparte thread!
}

// ... alle threads draaien nu parallel ...

// Wacht tot alle threads klaar zijn:
for(int n = 0; n < input.size(); ++n) {
    threads[n].join();
    if(!threads[n].succeeded()) {
        // Foutmelding weergeven.
    }
}


Ik heb wat extra code toegevoegd om ook te laten zien dat je de resultaten van een job (in dit geval 'succeeded') na afloop kunt bekijken. Zoals ik al eerder zei is het waarschijnlijk handig om het aantal parallelle threads enigzins te beperken, als je meer dan een stuk of 10~20 plaatjes gaat verwerken.

(Overigens heb ik dit even uit m'n hoofd ingetypt dus a.u.b. niet gaan muggenziften over style issues of een syntax error hier of daar ;))

[ Voor 22% gewijzigd door Soultaker op 17-01-2006 21:34 ]


Verwijderd

Topicstarter
Bedankt voor het voorbeeld, ik zal morgen kijken of ik het begrijp.


Je hoort van me.

Verwijderd

Topicstarter
Ik heb er even naar gekeken, de meeste code begrijp ik wel alleen de volgende regel niet zo goed.

Java:
1
 ImageProcessor[] = new ImageProcessor(input.length);


Je maakt een array van het object ImageProcessor of zoiets aan, maar ik weet niet goed wat. De default constructor van ImageProcessor heeft 2 parameters. Wat bedoel je met deze regel?

  • zwippie
  • Registratie: Mei 2003
  • Niet online

zwippie

Electrons at work

Dat moet waarschijnlijk zijn:
Java:
1
ImageProcessor[] = new ImageProcessor[input.length];

Maak een array van ImageProcessors, met precies evenveel elementen als de input array.

How much can you compute with the "ultimate laptop" with 1 kg of mass and 1 liter of volume? Answer: not more than 10^51 operations per second on not more than 10^32 bits.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-04 03:50
Inderdaad; zoals ik zei, heb ik het uit m'n hoofd getypt, dus er zullen wel meer van dit soort dingen in zitten. (Officieel kan ik ook helemaal geen Java :P)

Verwijderd

Topicstarter
Top, het doet het!!!

Met het voorbeeld is gelijk mijn vraag op de eerste post beantwoord. Ik dacht dat ik een thread met methodes op een andere manier werkte, door aan de hand van dit voorbeeld begrijp ik nu hoe ze met elkaar werken.

Bedank voor de hulp.
Pagina: 1