Problem z odpaleniem kilku wątków na raz

0

Witam,
W poniższym kodzie chce uruchomić dwa wątki na raz na rzecz jednego obiektu. Niestety najpierw pierwszy wątek wykonuje zadanie a potem dopiero nastepny. Co powinienem zeminic aby dwa watki dzialaly jednoczesnie ? Dopiero zaczynam sie uczyc watkow i prosze o pomoc. Kod poniżej:

 import java.util.*;
import javax.swing.*;


class Znak implements Runnable{
Pracownicy p=new Pracownicy();
Zasob a;
public int tnr=1;
public Znak(Zasob z){
a=z;
}
public void start()  {
          new Thread(this, "Nr " + tnr++).start();
}
public void run(){
   Thread cThread = Thread.currentThread();


		 int j=0;
	   int i=100000;
	   synchronized (this) {
	   while(j<3){
       while(i<1000000){
   	String haslo=p.inicjaly[j]+i;
       	System.out.println(cThread.getName()+haslo);
       	if(a.haslo(haslo)){
       		 try {
                  wait();
      } catch (InterruptedException exc) {
          System.out.println("Obsluga przerwania watku w stanie wait");
      }
       	}
        i++;
       	}
       	j++;
	   	}
	   }
	}








}
class Pracownicy{
	public static String[] inicjaly={"nt","at","kg"};
	public static String[] data={"220590","121188","230691"};
	public Pracownicy(){
	}
}
class Zasob{
	String haslo;
	public Zasob(String s){
		haslo="nt120000";
	}
	public boolean haslo(String s){
		if(s.equals(haslo)){
		return true;
		}
		else return false;
	}
}
class Main{
public static void main(String[] args) {
	int j=0;
	Pracownicy p=new Pracownicy();
	Random r=new Random();
	String i=p.inicjaly[r.nextInt(3)];
	i+=p.data[r.nextInt(3)];
	Zasob z=new Zasob(i);
    Znak t = new Znak(z);
    t.start();
    t.start();

    while(true){
    String haslo=JOptionPane.showInputDialog("Podaj haslo");
    if(z.haslo(haslo)){
    	break;
    }
    }
    System.exit(0);
  }
}
0

Ech, bo synchronozujesz sobie to w run() po this! Czyli po twoim obiekcie Znak. Ten kod to jest koszmar i bezsens, to tak ode mnie... Jak coś jest runnable to jest runnable a nie Thread. Napisz to jak człowiek. Zrób DWA obiekty Znak. Wywal to start() z tej klasy i pozwól użytkownikowi odpalić to Runnable tak jak chce.

0

Dopiero zaczynam zabawe z watkami i nie dokonca to rozumiem . Mogłbyś mnie bardziej naprowadzić co powinienem zrobic ? Moim zadanie jest aby podzielić pracę w części Znak pomiędzy wątki oraz mierzyć czas odnalezienia hasła w sytuacjach, gdy w części Znak zajmuje się tym jeden wątek, albo 2 albo 10, albo 100 albo jeszcze inna ich liczba. Mógłbyś mnie jakoś naprowadzić na rozwiązanie tego ? Coś podpowiedzieć

import java.util.*;
import javax.swing.*;
class Znak extends Thread{
Pracownicy p=new Pracownicy();
Zasob a;
String haslo;
public int i=0;
public int j=0;
public int tnr=1;
public Znak(Zasob z){
a=z;
}
public void run(){
	   while(j<3){
       while(i<1000000){
       	try {
          Thread.sleep(10);
        } catch(InterruptedException exc) { return; }
        synchronized(this){
        	if(i==1000001){
       		try {
          wait();
        } catch(InterruptedException exc) { return; }
       	}
    if(i<10){
    haslo=p.inicjaly[j]+"00000"+i;
    }
    else if(i<100){
    haslo=p.inicjaly[j]+"0000"+i;
    }
    else if(i<1000){
    haslo=p.inicjaly[j]+"000"+i;
    }
    else  if(i<10000){
    haslo=p.inicjaly[j]+"00"+i;
    }
    else  if(i<100000){
    haslo=p.inicjaly[j]+"0"+i;
    }
   	else{String haslo=p.inicjaly[j]+i;}
System.out.println(haslo);
       	if(a.haslo(haslo)){
             try {
         i=1000001;
         wait();
        }
       catch (InterruptedException exc) {
          System.out.println("Obsluga przerwania watku w stanie wait");
      }

        }
        else i++;
        }

       	}

       	j++;
	   	}

	}
}
class Pracownicy{
	public static String[] inicjaly={"nt","at","kg"};
	public static String[] data={"220590","121188","230691"};
	public Pracownicy(){
	}
}
class Zasob{
	String haslo;
	public Zasob(String s){
		haslo="nt001000";
	}
	public boolean haslo(String s){
		if(s.equals(haslo)){
			System.out.println("haslo prawidlowe");
		return true;
		}
		else return false;
	}
}
class Main{
public static void main(String[] args) {
	int j=0;
	Pracownicy p=new Pracownicy();
	Random r=new Random();
	String i=p.inicjaly[r.nextInt(3)];
	i+=p.data[r.nextInt(3)];
	Zasob z=new Zasob(i);
	int k=Integer.parseInt(JOptionPane.showInputDialog("Ilosc watkow"));
    while(j<k){
    Znak t = new Znak(z);
    t.run();
    j++;
    }

    while(true){
    String haslo=JOptionPane.showInputDialog("Podaj haslo");
    if(z.haslo(haslo)){
    	break;
    }
    }
    System.exit(0);
  }
}
 
0

Ale te twoje bazgroły nie mają nic wspólnego z daniem które masz do rozwiązania. A ty nie masz problemu z wątkami tylko z programowaniem obiektowym. Skasuj to wszystko, bo niewiele jest warte. Pomyśl, a potem napisz to od nowa.
Jesli chodzi o podział na wątki to ja zrobiłbym tu 2 klasy:

  • Pula wątków, do której podajesz ilość wątków operacyjnych i Obiekt do testowania poprawności hasła. Ta klasa tworzy odpowiednią ilość wątków i dzieli pracę między nie (tzn podaje każdemu wątkowi obiekt do testowania oraz zakres haseł do łamania)
  • Wątek który dostaje informacje o obiekcie do testowania poprawności hasła i zakres haseł które ma łamać i w pętli bawi się w łamanie hasła.
0

Poszedlem za twoja rada i troche przysiadlem do tego mam takie cos :

import java.util.*;
import javax.swing.*;
abstract class Proces extends Thread {
    protected String[] inicjaly;
    protected Password password;

    public Proces(Password password, String[] inicjaly) {
        setPassword(password);
        setInicjaly(inicjaly);
    }

    public void setInicjaly(String[] inicjaly) {
        this.inicjaly = inicjaly;
    }

    public void setPassword(Password password) {
        this.password = password;
    }
}

class Pracownicy {
    static String[] inicjaly={"nt"};
    static String[] daty={"230990"};


    public Pracownicy() {

    }

    public String[] getInicjaly() {

        return inicjaly;
    }

    public String[] getData() {
        return daty;
    }
}
class GrupaA extends Proces {
    protected int from = 0;
    protected int to = 1000000;

    public GrupaA(Password password, String[] initials, int from, int to) {
        super(password, initials);
        this.from = from;
        this.to = to;
    }

    public void run() {
        String passCandidate;
        while (password.isPassUnknown()) {
            for (int x = 0; x < inicjaly.length; x++) {
                for (int y = from; y < to; y++) {
                    passCandidate = inicjaly[x]
                            + (("" + (1000000 + y)).substring(1));
                    if (password.compare(passCandidate)) {
                        password.setPassBroken();
                        System.out.println("Hasło złamane: " + passCandidate);
                        return;
                    }
                }
            }
            break;
        }
    }
}
class GrupaAwatki {
    protected int threadsNum = 0;

    public GrupaAwatki(int threadsNum) {
        this.threadsNum = threadsNum;
    }

    public void startGroups(Password password, String[] initials) {
        if (threadsNum == 0) {
            threadsNum = initials.length;
        }
        GroupA[] threads = new GroupA[threadsNum];

        int limit = 1000000;
        int part = limit / threadsNum;
        int from = 0 - part;
        int to = 0;

        int x = 0;
        boolean workFlag = true;
        do {
            from += part;
            if (to + part < limit && x + 1 < threadsNum) {
                to += part - 1;
            } else {
                to = limit;
                workFlag = false;
            }

            threads[x] = new GroupA(password, initials, from, to);
            threads[x].start();
            x++;
        } while (workFlag);
        System.out.println("Uruchomiono " + x + " wątków grupy A");
    }
}
class GrupaB extends Proces {
    public GrupaB(Password password, String[] initials) {
        super(password, initials);
    }

    public void run() {
        String passCandidate, input;

        String message = "Nasze propozycje haseł";

        while (password.isPassUnknown()) {
            passCandidate = "";
            input = JOptionPane.showInputDialog(message);

            if (input == null) {
                return;
            } else if (password.compare(input)) {
                password.setPassBroken();
                System.out.println("Hasło złamane: " + passCandidate);
                return;
            } else {
                System.out.println("nie udało się");
            }
        }
    }
}


class Password {
    protected boolean passBroken = false;
    protected String password;

    public boolean compare(String password) {
        return this.password.equals(password) ? true : false;
    }

    public boolean isPassUnknown() {
        return !passBroken;
    }

    public void generate(String[] inicjaly,String[] daty) {
        int randomIndex = (int) (inicjaly.length * Math.random());
        password = inicjaly[randomIndex]+daty[randomIndex];
    }

    public String getPassword() {
        return password;
    }

    public void setPassBroken() {
        passBroken = true;
    }
}
class Timer extends Thread {
    protected int counter;
    protected Password password;
    protected boolean running = true;

    public Timer(Password password) {
        this.password = password;
    }

    public void stopTimer() {
        this.running = false;
    }

    public void run() {
        while (running && !password.passBroken) {
            try {
                counter++;
                System.out.println("Czas: " + (counter / 60) + ":"
                        + (counter % 60));
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Main {
    public static void main(String[] args) {
        int threads;
        try {
            threads = Integer.parseInt(JOptionPane.showInputDialog("Podaj ilosc watkow Grupy A")); // liczba watkow - manualna
        } catch (ArrayIndexOutOfBoundsException e) {
            threads = 0;
        }

        Pracownicy employee = new Pracownicy();
        Password password = new Password();

        password.generate(employee.getInicjaly(),employee.getData());

        System.out.println("Wylosowane haslo: " + password.getPassword());

        GrupaAwatki grAw = new GrupaAwatki(threads);
        GrupaB grB = new GrupaB(password, employee.getInicjaly());

        Timer timer = new Timer(password);
        timer.start();

        grAw.startGroups(password, employee.getInicjaly());
        grB.setPriority(8);
        grB.start();
    }
}

 

Co bys zmienil ? Teraz program dziala prawidlowo . Jedna grupa wpisuje haslo recznie druga wyszukuje automatycznie.

0

Nie rozumiem czemu wątek do ręcznego łamania nazywa się "grupa". Poza tym jeśli wykonujesz jakieś operacje typu set() na obiekcie to powinieneś to miejsce synchronizować na tym obiekcie, chociaż tutaj akurat chyba nie ma żadnego race condition ani concurrent modification, ale mimo wszystko warto o tym pamiętać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1