Задание: Выполнить приложение командной строки с двумя параметрами, один из которых – количество потоков, другой параметр – количество выводимых строк. Нужно так синхронизовать потоки, чтобы имена потоков выводились поочередно- в каждой строке. Под синхронизацией подразумевается использование конструкции synchronized и методов wait, notify. Не использовать в этом задании флаги для синхронизации потоков, а только методы wait и notify. Также не использовать любые задержки для потоков после начала их работы в виде методов sleep, yield или wait c параметром. Имя первого потока должно всегда выводится в новой строке.
Пример вывода для приложения с параметрами 3 и 2:
Thread-0 Thread-1 Thread-2
Thread-0 Thread-1 Thread-2
Мой код:
class Task implements Runnable {
private Task prevTask;
private int number;
static private int numberOfLines;
static private int numberOfTasks;
static private boolean isBegin;
Task(int number) {
this.number = number;
}
void setPrevTask(Task prevTask) {
this.prevTask = prevTask;
}
static void setStaticFields(int numberOfLines, int numberOfTasks) {
Task.numberOfLines = numberOfLines;
Task.numberOfTasks = numberOfTasks;
Task.isBegin = true;
}
@Override
public void run() {
for (int i = 0; i < numberOfLines; i++) {
if (isBegin && number == 0) {
isBegin = false;
} else {
synchronized (prevTask) {
try {
prevTask.wait();
} catch (InterruptedException ie) {
System.err.println("Thread " + Thread.currentThread().getName() + " was interrupted");
}
}
}
synchronized (this) {
System.out.print(Thread.currentThread().getName() + " ");
if (number == numberOfTasks - 1) {
System.out.println();
}
this.notify();
}
}
}
public class Lab4 {
public static void main(String[] args) {
try {
if (args.length != 2) {
throw new IllegalArgumentException("Illegal number of arguments");
}
int numberOfTasks = Integer.parseInt(args[0]);
int numberOfLines = Integer.parseInt(args[1]);
Task.setStaticFields(numberOfLines, numberOfTasks);
Task[] tasks = new Task[numberOfTasks];
for (int i = 0; i < numberOfTasks; i++) {
tasks[i] = new Task(i);
}
for (int i = 1; i < numberOfTasks + 1; i++) {
int index = (i + numberOfTasks) % numberOfTasks;
tasks[index].setPrevTask(tasks[(numberOfTasks + i - 1) % numberOfTasks]);
new Thread(tasks[index], "Thread-" + index).start();
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
Здесь происходит блокировка потоков. Я правильно понимаю, что когда-то notify вызывается раньше, чем соответствующий wait или проблема в другом? Как можно это не допустить или исправить?
Мне кажется чтобы совсем голову не сломать здесь надо применить очередь сообщений. Вспомним Алана Кея и его знаменитые фразы:
Я считал объекты чем-то вроде биологических клеток, и/или отдельных компьютеров в сети, которые могут общаться только через сообщения.
Большая идея это «сообщения»
public class WThread2 extends Thread {
private static int numberOfLines;
private static int numberOfThreads;
private static final Queue<Message> messageQueue = new LinkedList<>();
public static synchronized void addMessage(Message msg){
messageQueue.add(msg);
}
private static synchronized Message getMessage(){
return messageQueue.peek();
}
private static synchronized Message remove(){
return messageQueue.poll();
}
public static void main(String[] args) {
//Читаем входные параметры
if (args.length != 2) {
throw new IllegalArgumentException("Illegal number of arguments");
}
numberOfThreads = Integer.parseInt(args[0]);
numberOfLines = Integer.parseInt(args[1]);
//Создаем и запускаем потоки
Worker[] workers;
workers = new Worker[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++){
workers[i] = new Worker();
workers[i].start();
}
//Создаем очередь сообщений
for(int i = 0; i < numberOfLines; i++){
for(int j = 0; j < numberOfThreads; j++) {
addMessage(new Message(Thread.currentThread(), workers[j], workers[j].getName()));
}
addMessage(new Message(Thread.currentThread(), workers[0], "\n"));
}
synchronized (Worker.class) {
Worker.class.notifyAll();
}
while (!messageQueue.isEmpty()){
synchronized (Worker.class) {
try {
Worker.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static class Worker extends Thread{
public Worker(){
setDaemon(true);
}
@Override
public void run() {
super.run();
synchronized (Worker.class) {
while(true) {
try {
Worker.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = getMessage();
if (msg!=null && msg.from.getName().equals("main") && msg.to == this) {
remove();
System.out.print(msg.txt());
}
Worker.class.notifyAll();
}
}
}
}
public static class Message{
public final Thread from;
public final Thread to;
private final String txt;
public Message(final Thread from, final Thread to, final String txt){
this.from = from;
this.to = to;
this.txt = txt;
}
public String txt(){
return txt + " ";
}
}
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
хотелось проверить получение параметров на их валидность и выбросить исключение с соответствующим описанием ошибки, для этого как я понимаю...
Как в css сделать так, чтобы высота дочернего блока занимала всю высоту родительского? Высота родительского блока при этом не определена
Столкнулась со следующей проблемой, которую хотелось бы решить лаконичнее в одну строкуНеобходимо чтобы при наведении на пункты меню появлялось...
Да, возможно тупой вопрос, но я новичок