Witam.
Dopiero zaczynam moją przygotę z programowaniem współbieżnym i zostało mi postawione na uczelni zadanie (treść na samym końcu). Zadanie napisałem, jednak problem polega na tym, że po sprawdzeniu go przez program sprawdzający otrzymałem jedynie część punktów, otrzymując takie powiadomienia wyjaśniające powód odjęcia punktów:
- do kończenia watku należało uzyć metody interrupt()
-należało sprawdzać flagę interrupted metodą interrupted lub isInterrupted
- brak wątku przerywającego w metodzie main
Oczywiście nie jestem do końca pewny czy zadanie wykonałem poprawnie...(jak wiadomo w przypadku wątków trochę zależy też od szczęścia przy testowaniu)...
public class StringTask implements Runnable {
private TaskState currentState;
private String stringToMultiply;
private int howMany;
private String resultString;
private Thread task;
private volatile boolean taskShouldBeRunning;
public StringTask(String stringToMultiply,int howMany) {
this.howMany=howMany;
this.stringToMultiply=stringToMultiply;
this.currentState=TaskState.CREATED;
this.task=new Thread(this);
this.taskShouldBeRunning=false;
this.resultString="";
}
//2 konstruktor po to by mozna bylo uruchomic nastepne zadanie (watek)
//zaczynajac od stanu "wypracowanego" przez inny
public StringTask(String stringToMultiply,int howMany,String resultString ) {
this.howMany=howMany;
this.stringToMultiply=stringToMultiply;
this.currentState=TaskState.CREATED;
this.task=new Thread(this);
this.taskShouldBeRunning=false;
this.resultString=resultString;
}
//2 get'ery po to by mozna bylo uruchamiac zadania
//poczynajac od stanu "wypracowanego" przez inne zadanie
public String getStringToMultiply() {
return stringToMultiply;
}
public int getHowMany() {
return howMany;
}
/************WYMAGANE METODY*******************/
public void start() {
taskShouldBeRunning=true;
task.start();
}
public void abort() {
taskShouldBeRunning=false;
//currentState=TaskState.ABORTED; po to by uzyskac 2 efekt.. z tresci zadania...
//task.interrupt(); //chyba tutaj (zgodnie z błędami ze sprawdzania musi być interrupt?)
}
public String getResult() {
return resultString;
}
//zwraca biezacy stan zadania
public TaskState getState() {
return currentState;
}
public boolean isDone() {
if(currentState.equals(TaskState.READY)||currentState.equals(TaskState.ABORTED))return true;
return false;
}
//w metodzie run() wykonywane jest powielanie napisu
@Override
public void run() {
multiplyString();
}
private void multiplyString() {
while(taskShouldBeRunning) { //czy tutaj trzeba sprawdzać flagę interrupt??
int helper=howMany;
for(int i=0;i<helper && taskShouldBeRunning;i++) {
currentState=TaskState.RUNNING;
resultString=resultString+stringToMultiply;
howMany--;
}
if(howMany==0) {
currentState=TaskState.READY;
return ;
}
}
currentState=TaskState.ABORTED;
}
}
Poniżej jeszcze main i w miarę oczywisty enum...
public enum TaskState {
CREATED,RUNNING,ABORTED,READY;
}
public class Main {
public static void main(String[] args) throws InterruptedException {
StringTask task = new StringTask("A", 70000);
System.out.println("Task " + task.getState());
task.start();
if (args.length > 0 && args[0].equals("abort")) {
/*<- tu zapisać kod przerywający działanie tasku po sekundzie
i uruchomić go w odrębnym wątku
*/
Thread.sleep(1000);
task.abort();
StringTask task2=new StringTask(task.getStringToMultiply(),task.getHowMany(),task.getResult());
}
while (!task.isDone()) {
Thread.sleep(500);
switch(task.getState()) {
case RUNNING: System.out.print("R."); break;
case ABORTED: System.out.println(" ... aborted."); break;
case READY: System.out.println(" ... ready."); break;
default: System.out.println("unknown state");
}
}
System.out.println("Task " + task.getState());
System.out.println(task.getResult().length());
}
}
I treść zadania...
Uruchamianie i zatrzymywanie równoległego działania kodów
Zbudować klasę StringTask, symulująca długotrwałe obliczenia, tu polegające na konkatenacji napisow.
Konstruktor klasy otrzymuje jako argument napis do powielenia oraz liczbę oznaczającą ile razy ten napis ma być powielony.
Klasa winna implementować interfejs Runnable, a w jej metodzie run() wykonywane jest powielenia napisu, przy czym to powielenia ma się odbywac za pomoca operatora '+' stosowanego wobec zmiennych typu String (to właśnie długotrwała operacja). Użycie '+' jest warunkiem obowiązkowe.
Obiekt klasy StringTask traktujemy jako zadanie, które może się wykonywać równolegle z innymi.
Możliwe stany zadania to:
CREATED - zadanie utworzone, ale nie zaczęło się jeszcze wykonywać,
RUNNING - zadanie się wykonuje w odrebnym wątku
ABORTED - wykonanie zadania zostało przerwane
READY - zadanie zakończyło się pomyślnie i sa gotowe wyniki.
W klasie StringTask zdefiniować metody:
public String getResult() - zwracającą wynik konkatenacji
public TaskState getState() - zwracającą stan zadania
public void start() - uruchamiającą zadanie w odrębnym watku
public void abort() - przerywającą wykonanie kodzu zadania i działanie watku
public boolean isDone() - zwracająca true, jeśli wykonanie zadania się zakończyło normalnie lub przez przerwanie, false w przeciwnym razie
Poniższy kod program:
public class Main {
public static void main(String[] args) throws InterruptedException {
StringTask task = new StringTask("A", 70000);
System.out.println("Task " + task.getState());
task.start();
if (args.length > 0 && args[0].equals("abort")) {
/*<- tu zapisać kod przerywający działanie tasku po sekundzie
i uruchomic go w odrębnym wątku
*/
}
while (!task.isDone()) {
Thread.sleep(500);
switch(task.getState()) {
case RUNNING: System.out.print("R."); break;
case ABORTED: System.out.println(" ... aborted."); break;
case READY: System.out.println(" ... ready."); break;
default: System.out.println("uknown state");
}
}
System.out.println("Task " + task.getState());
System.out.println(task.getResult().length());
}
}
uruchominy bez argumentu powinien wyprowadzić coś w rodzaju:
Task CREATED
R.R.R.R.R.R.R.R.R. ... ready.
Task READY
70000
a uruchomiony z argumentem "abort" może wyprowadzić:
Task CREATED
R. ... aborted.
Task ABORTED
31700
Uwaga 1. Plik Main.java może być modyfikowany tylko w miejscu oznaczonym /*<- */
Uwaga 2. Nie wolno uzywac metody System.exit(...)
Z góry dziękuję wszyskitm, którzy przekopią się przez tak długą treść i postarają się mi pomóc.
Pozdrawiam.