Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Hallo
Zur Einführung habe ich hier ein kleines Programm.
Ich habe dazu 3 Klassen. Die Klasse Thread hat 3 Methoden, start, sleep, run.
Die Anweisungen stehen zwar in der run Methode aber es wird trotzdem irgendwie die start Methode im Main verwendet.
Warum funktiioniert das jetzt nicht?
Eigentlich sollte jetzt ein Plus kommen um zu zeigen, dass die main vorher fertig wird und ich sollte auch sehen, dass sich .*.*.*.*.*.* irgendwie nacheinander wiederholt. Tut es aber nicht.
Java:
public class CharPrinter extends Thread {
char signal;
public CharPrinter(char ch) {
signal = ch;
}
public void run() {
for (int i = 0; i < 20; i++) {
System.out.print(signal);
int delay = (int) (Math.random() * 1000);
try {
sleep(delay);
} catch (Exception e) {
return;
}
}
}
}
Java:
public class Thread {
public void start() {}
public static void sleep(int milliSeconds) {}
public void run() {
}
}
Java:
class Program {
public static void main(String[] arg) {
CharPrinter thread1 = new CharPrinter('.');
CharPrinter thread2 = new CharPrinter('*');
thread1.start();
thread2.start();
System.out.print('+');
}
}
+*...*.*.*..**.**..*.*...***.*..*.*..****
Ich habe Deinen Code mal laufen gelassen.
Bei mir kommt zuerst ein +.
Dass sich * und Punkt nicht gleichmäßig abwechseln hängt damit zusammen, dass nicht sichergestellt ist wie die Thread abgearbeitet werden. Damit muss man beim Programmieren mit Threads aber rechenen.
Hi danke
Das weiss ich schon, aber wenn ich es laufen lasse, kommt bei mir nur ein plus..
sprich ich führe die main aus, stimmt das
thread1.start() überhaupt.
Denn es gibt ja keine start() Methode
Ich habe Deinen Code laufen lassen, wie gesagt. Die Ausgabe sieht bei mir etwa so aus
+*...*.*.*..**.**..*.*...***.*..*.*..****
Und thread1 hat natürlich die Methode start(), weil es ja vom Type CharPrinter ist der wiederum von Thread abgeleitet ist. Und Thread hat ja bereits die Methoden start() run() usw.
Du solltest deinen CharPrinter schon von dem Java-Thread ableiten. Bei dir passiert nichts, weil du deine eigene Klasse Thread erstellt hast, die halt nichts macht
Es gibt ja da die run-Methode. Wie mache ich das jetzt zB, dass nicht alles in der run-Methode ist?
Was ich meine ist, was passiert, wenn ich eine andere Methode noch erstellen möchte im CharPrinter?
So wie ich das verstehe, kann ich das ja nur in run implementieren und danach dann in der main mit start() starten..
In meinen Augen ist das irgendwie unflexibel, aber das mein ich vielleicht nur, weil ich keine Ahnung habe oder?
ok, das heisst also, ich müsste den ganzen Code oder die ganzen Anweisungen alle in run implementieren und daraus dann eben einfach auf all die Methoden zugreifen.
Was meintest du mit Runnable?
Anstatt extends Thread
extends Runnable und warum?
Das hast du ja in jedem Programm. Genauso hast du ja nur eine main-Methode und musst daraus alles aufrufen.
Du hast den Vorteil dass du mehrere Interfaces implementieren kannst und wenn du Runnable implementierst kannst du außerdem noch von einer Klasse erben. Wenn du von Thread erbst geht das nicht mehr, da Mehrfachvererbung in Java nicht möglich ist.
Bietet sich außerdem an wenn du später nochmal mit sowas wie ThreadPools und FutureTasks arbeiten willst.
Rein von der Logik her möchtest du ja auch nur eine ausführbare Aufgabe übergeben und nicht irgendein threadspezifisches Verhalten ändern.
Mit Runnable wäre das dann so:
Java:
class Program {
public static void main(String[] arg) {
CharPrinter thread1 = new CharPrinter('.');
CharPrinter thread2 = new CharPrinter('*');
new Thread(thread1).start();
new Thread(thread2).start();
System.out.print('+');
}
}
Java:
public class CharPrinter implements Runnable {
char signal;
public CharPrinter(char ch) {
signal = ch;
}
public void run() {
for (int i = 0; i < 20; i++) {
System.out.print(signal);
int delay = (int) (Math.random() * 1000);
try {
Thread.sleep(delay);
} catch (Exception e) {
return;
}
}
}
}
Ich habe hier eine Klasse, die threadsicher gemacht werden soll.
Dafür müsste man synchronized verwenden, damit sich die Threads nicht in die Quere kommen.
Reicht es in diesem Fall einfach synchronized Methoden daraus zu machen?
aus
Java:
public class Stack {
private Object[] array;
private int index;
Stack(int size) {
array = new Object[size];
}
public void put(Object o) {
if (index<array.length) {
array[index] = o;
index = index + 1;
}
}
public Object get() {
if (index==0) return null;
Object o = array[index];
index = index - 1;
return o;
}
}
wird
Java:
public class Stack {
private Object[] array;
private int index;
Stack(int size) {
array = new Object[size];
}
public synchronized void put(Object o) {
if (index<array.length) {
array[index] = o;
index = index + 1;
}
}
public synchronized Object get() {
if (index==0) return null;
Object o = array[index];
index = index - 1;
return o;
}
}
Wie funktioniert das mit dem synchronized (lock) eigentlich?
Und wie müsste ich dies hier machen?
Das kann ich hier aus dem Text irgendwie nicht ganz herausfiltern.
Threas1 holt sich praktisch den 'Lock' an dem Objekt. Wenn Thread2 an die Stelle kommt und versucht sich auch den Lock zu holen, geht das nicht weil Thread1 diesen noch hat. Er wartet also so lange bis Thread1 den Block verlässt und den Lock freigibt. Danach holt sich Thread2 den Lock und kann den Block ausführen.
Wenn eine Methode synchronized ist, wird implizit einfach ein Lock auf das this-Objekt gemacht. Folgende Source-Codes verhalten sich also gleich:
Java:
public synchronized Object get() {
if (index == 0)
return null;
Object o = array[index];
index = index - 1;
return o;
}
Java:
public Object get() {
synchronized (this) {
if (index == 0)
return null;
Object o = array[index];
index = index - 1;
return o;
}
}
In diesem Fall könntest du dich aber auch zum Beispiel an dem Array synchronisieren.
danke, aber das verstehe ich nicht, wieso an dem Array? Und warum kann man das an einem Array.
Genauso könnte ich ja auch sagen, na dann machen wir es doch am Index?!
Und das kann durchaus sinnvoll sein. Wenn du Ressource A und Ressource B hast und zwei Threads dann ist es nicht unbedingt sinnvoll sich am this Objekt zu synchronisieren.
Wenn Thread1 nur etwas mit A machen will, dann muss Thread2 warten obwohl er mit Ressource B etwas machen könnte.
Bei sowas ist es dann sinnvoller sich an A bzw. B zu synchronisieren.
Ist aber von Fall zu Fall unterschiedlich und man muss immer mit Race Conditions und Deadlocks aufpassen.
Ich habe mich mal inzwischen an einem Beispiel versucht, was irgendwie immer noch nicht hinhaut.
Gesucht ist eine Klasse Terminator. Ein „Terminator“ zählt im Sekundentakt von 10 nach 0. Anschliessend beendet er mit System.exit(1) brutal die laufende Applikation. a) Implementieren Sie die Klasse, so dass sie mit dem untenstehenden Code zusammen funktioniert.
Java:
public class TerminatorDemo {
public static void main(String[] args) {
Terminator t = new Terminator();
t.start();
while (true) {} } }
b) Ergänzen Sie die Klasse um eine Methode disable(), so dass ein „Terminator“ auch abgebrochen werden kann.
Lösung:
Java:
import java.util.concurrent.TimeUnit;
public class Terminator implements Runnable{
private int i = 10;
private int time;
Terminator(int time){
this.time = time;
}
public void run(){
System.out.println(i);
try {
TimeUnit.MILLISECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 0){
disable();
}
i--;
}
public void disable(){
System.exit(1);
}
}
Java:
public class TerminatorDemo {
public static void main(String[] args) {
Terminator t = new Terminator(1000);
t.start();
while (true) {
}
}
}
er meckert irgendwie an dem t.start();
und wofür ist die while??
public class TerminatorDemo {
public static void main(String[] args){
Terminator t = new Terminator(1000);
Thread object = new Thread(t);
object.start();
}
}
Java:
import java.util.concurrent.TimeUnit;
public class Terminator implements Runnable{
private int i = 10;
private int time;
Terminator(int time) {
this.time = time;
}
public void run(){
while (i >= 0) {
System.out.println(i);
try {
TimeUnit.MILLISECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i == 0) {
disable();
}
i--;
}
}
public void disable() {
System.exit(1);
}
}
mit welchem Befehl mache ich das denn?
und wie macht man das zur Laufzeit?
Baue ich da was Fixes in die main oder passiert das mit Tastenkombination von aussen?
Also ich hab das grad mal versucht, aber irgendwie kommt eine NullPointer
und bis dann aber disable() ausgeführt wird, wird ja zuerst mal runtergezählt..
Wie soll das denn gehen, dass ich den Thread während der Laufzeit abbrechen kann..?
Java:
public class TerminatorDemo {
static Thread object;
public static void main(String[] args) {
Terminator t = new Terminator(1000);
Thread object = new Thread(t);
object.start();
disable();
}
public static void disable(){
object.stop();
}
}
public class TerminatorDemo {
static Thread object;
public static void main(String[] args) {
Terminator t = new Terminator(1000);
Thread object = new Thread(t);
object.start();
}
}
Java:
import java.util.concurrent.TimeUnit;
public class Terminator implements Runnable{
private int i = 10;
private int time;
boolean run = true;
Terminator(int time) {
this.time = time;
}
public void run(){
while (run & i >= 0) {
System.out.println(i);
try {
TimeUnit.MILLISECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i == 0) {
exit();
}
i--;
if (i==6){
disable();
}
}
}
public void exit() {
System.exit(1);
}
public void disable(){
run = false;
}
}
Soo, ich war doch ein wenig fleissig und hab da was gebastelt.
Warum funktioniert das nun, mit
TimeUnit.MILLISECONDS.sleep(delay);
aber nicht mit
sleep(delay);
Java:
public class test {
public static void main(String[] args) {
CharPrinter2 t1 = new CharPrinter2();
Thread object1 = new Thread(t1);
object1.start();
}
}
Java:
import java.util.concurrent.TimeUnit;
public class CharPrinter2 implements Runnable {
String signal;
int delay = 1000;
public CharPrinter2() {
}
public void run() {
CharReader t2 = new CharReader();
Thread charreader = new Thread(t2);
charreader.start();
signal = t2.getSignal();
for (int i = 0; i < 100; i++) {
try {
System.out.print(signal);
signal = t2.getSignal();
TimeUnit.MILLISECONDS.sleep(delay);
} catch (Exception e) {
return;
}
}
}
}
Java:
import java.util.Scanner;
public class CharReader implements Runnable {
private String signal = "AudiRS4";
public CharReader() {
}
public void run() {
while(true){
Scanner sc = new Scanner(System.in);
System.out.println("Zeichen?");
signal = sc.nextLine();
}
}
public String getSignal(){
return signal;
}
}