Нечетная печать четного числа с использованием нити - PullRequest
7 голосов
/ 16 мая 2011

Печать нечетного четного числа с использованием потока. Создайте один класс потока, два экземпляра потока.Один напечатает нечетное число, а другой напечатает четное число.

Я сделал следующую кодировку.Но дело доходит до тупика.Кто-нибудь может объяснить, в чем может быть причина?

public class NumberPrinter implements Runnable{
private String type;
private static boolean oddTurn=true;


public NumberPrinter(String type){
    this.type=type;
}
public void run() {
    int i=type.equals("odd")?1:2;
    while(i<10){
        if(type.equals("odd"))
            printOdd(i);
        if(type.equals("even"))
            printEven(i);
        i=i+2;
    }

}

private synchronized void printOdd(int i){
    while(!oddTurn){
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println(type + i);
    oddTurn=false;
    notifyAll();
}

private synchronized  void printEven(int i){
    while(oddTurn){
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace(); 
        }
    }
    System.out.println(type + i);
    oddTurn=true;
    notifyAll();

}

public static void main(String[] s){
    Thread odd=new Thread(new NumberPrinter("odd"));
    Thread even=new Thread(new NumberPrinter("even"));
    odd.start();
    even.start();

}
}

Out Put: odd1 even2


затем заходит в тупик !!!!!!

Спасибо за вашу помощь.

Ответы [ 11 ]

13 голосов
/ 16 мая 2011

Вы ожидаете и уведомляете различные объекты ( мониторы ).

Идея состоит в том, что вы можете позвонить obj.wait() и ждать, пока кто-нибудь сделает obj.notify(), пока вы делаете objA.wait() и objB.notify().

Измените свой printOdd метод на что-то вроде

private void printOdd(int i) {
    synchronized (lock) {                        // <-------
        while (!oddTurn) {
            try {
                lock.wait();                     // <-------
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + i);
        oddTurn = false;
        lock.notifyAll();                        // <-------
    }
}

и метод printEven аналогично.

Затем предоставьте NumberPrinter объект lock:

Object lock = new Object();
Thread odd = new Thread(new NumberPrinter("odd", lock));
Thread even = new Thread(new NumberPrinter("even", lock));

Выход:

odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9
4 голосов
/ 16 мая 2011

В коде много ошибок.

Прежде всего, операторы synchronized не имеют никакого эффекта.Вы создаете два экземпляра потока, и каждый вызывает только свои собственные методы.synchronized полезно только в том случае, если другой поток может вызвать метод.

Тогда notifyAll() не действует по тем же причинам.odd.notifyAll() не достигает even висящего в wait().

Так что вам нужен еще один объект, который содержит состояние и который оба потока могут видеть и использовать.Используйте synchronized, wait() и notifyAll() для этого третьего экземпляра.

2 голосов
/ 03 мая 2014

То же самое можно решить с помощью интерфейса блокировки:

NaturalOrder.java

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NaturalOrder {

    public int currentNumber = 1;
    public boolean evenOdd = false;

    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public static void main(String[] args) {
        NaturalOrder naturalOrder = new NaturalOrder();
        Thread t1 = new Thread(new OddNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        Thread t2 = new Thread(new EvenNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        t1.start();
        t2.start();
    }
}

OddNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class OddNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public OddNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != false) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (naturalOrder.currentNumber % 2 != 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = true;

            condition.signalAll();
        }
        lock.unlock();
    }
}

EvenNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class EvenNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public EvenNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != true) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (naturalOrder.currentNumber % 2 == 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = false;
            condition.signalAll();
        }
        lock.unlock();
    }
}
1 голос
/ 23 ноября 2012

Я так и сделал

public class OddEven{
        public static void main(String[] args){
            Print o=new Print();
            Thread even=new Thread(new MyRunnable(2,o));
            Thread odd=new Thread(new MyRunnable(1,o));
            even.start();
            odd.start();
        }
}
class MyRunnable implements Runnable{
        int start;
        Print ob;
        MyRunnable(int s,Print o){
            start=s;
            ob=o;
        }
        public void run(){
            for(int i=start;i<=20;i+=2)
                ob.display(i);
        }   
}
class Print{
        int rem=0;
        synchronized void display(int n){
            while(n%2==rem)
                try{
                    wait();
                }
                catch(Exception e){System.out.println("Display interrupted");}
            System.out.print(n+" ");
            rem=n%2;
            notify();
        }           
}
1 голос
/ 16 мая 2011

Я думаю, что проблема может заключаться в том, что printOdd и printEven синхронизируются при другой блокировке (блокировка экземпляра объекта Thread).Поэтому вы не гарантировали, что изменение статической переменной oddTurn будет видно в другом потоке.Попробуйте сделать oddTurn волатильным для начала.

0 голосов
/ 19 октября 2014

Я реализовал таким образом, основываясь на аргументе, ни один из потоков не будет порожден и будет соответственно нет в циклическом порядкето есть, если число потоков равно 3, поток 1 напечатает 1,4 ...;нить 2 напечатает 2,5, ... а нить 3 напечатает 3,6 ...

public class ThreadSynchronizer
{

    public static void main(String[] args)
    {
    // BASED ON THE ARGUMENT MULTIPLE THREADS WILL BE CREATED AND EACH WILL PRINT ITS RESPECTIVE NO
    // IE, IF THREAD COUNT IS 3, THREAD 1 WILL PRINT 1,4 ..., THREAD2 WILL PRINT 2,5,... AND THREAD3 WILL PRINT 3,6...
    // LIMITED THE DISPLAY TO 1000 NOS
    int threadCnt = Integer.parseInt(args[0]);

    ReentrantLock lckArray[] = new ReentrantLock[threadCnt + 1];

    for (int i = 0; i < threadCnt + 1; i++)
    {
        ReentrantLock lck = new ReentrantLock();
        lck.lock();
        lckArray[i] = lck;
    }

    for (int i = 0; i < threadCnt; i++)
    {
        Thread th = new Thread(new Printer(lckArray, i + 1));
        th.start();
    }

    for (int i = 1; i < threadCnt + 1; i++)
    {
        lckArray[i].unlock();

        while (!lckArray[i].isLocked())
        {

        }
    }
    lckArray[0].unlock();
    }
}

class Printer implements Runnable
{

    private ReentrantLock[] lckArray;
    private int index;

    Printer(ReentrantLock[] lckArray, int startValue)
    {
    this.lckArray = lckArray;
    this.index = startValue;
    }

    @Override public void run()
    {
    ReentrantLock prevLock = null;
    int printCounter = index;

    for (int counter = 0; printCounter <= 1000; counter++)
    {
        int remCounter = counter % lckArray.length;
        int incCounter = lckArray.length - remCounter;
        int indexPostion = index + incCounter;
        int curElementIndex = indexPostion % lckArray.length;

        lckArray[curElementIndex].lock();
        if (prevLock != null)
        prevLock.unlock();
        prevLock = lckArray[curElementIndex];

        if (curElementIndex == 0)
        {
        System.out.println("Printed by Thread " + index + " " + printCounter);
        printCounter = printCounter + lckArray.length - 1;
        }

    }

    if (prevLock != null)
    {
        if (prevLock.isHeldByCurrentThread())
        prevLock.unlock();
    }

    }

}
0 голосов
/ 26 сентября 2014
public class Number_Thread extends Thread {

String thread;
int limit;

public Number_Thread(String thread,int limit){
    this.thread=thread;
    this.limit=limit;
                                             }

Object lock=new Object();

public  void run()
{

    synchronized (lock) 
    {

          //------------------- "print even"--------------------//

      if(thread.equals("even"))
        {
            for (int i = 2; i <=limit; i+=2) 
            {

                 System.out.println(thread+" thread "+i);
            try {

            lock.wait(1000);
                 continue;

                }
              catch (InterruptedException e) {}
            }
            lock.notifyAll();
        }

         //------------------- "print odd"--------------------//

    if(thread.equals("odd"))
         {
         for (int i = 1; i <=limit; i+=2) 
             {
                System.out.println(thread+" thread  "+i);
            try {

                lock.wait(1000);
                    continue;
                }
            catch (InterruptedException e) {}
            }
            lock.notifyAll();
         }
      }
   }
}

     //------------------thread creater class------------------//
import java.util.Scanner;

public class Main_Thread {
private static Scanner s;
    public static void main(String[] args) throws InterruptedException {
        System.out.print("enter limit:\t ");
        s=new Scanner(System.in);
    int n=s.nextInt();
     s.close();
    Thread t1=new Number_Thread("even",n);
    Thread t2=new Number_Thread("odd",n);
    t2.start();
    Thread.sleep(100);
    t1.start();

 }

}

выход для предела 5:

введите предел: 5

нечетная нить 1 четная нить 2 нечетная нить 3 четная нить 4 нечетная нить 5

0 голосов
/ 03 мая 2014

Ваш код исправлен с использованием интерфейса блокировки:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NumberPrinter implements Runnable {
    private Lock lock;
    private Condition condition;
    private String type;
    private static boolean oddTurn = true;

    public NumberPrinter(String type, Lock lock, Condition condition) {
        this.type = type;
        this.lock = lock;
        this.condition = condition;
    }

    public void run() {
        int i = type.equals("odd") ? 1 : 2;
        while (i <= 10) {
            if (type.equals("odd"))
                printOdd(i);
            if (type.equals("even"))
                printEven(i);
            i = i + 2;
        }
    }

    private void printOdd(int i) {
        // synchronized (lock) {
        lock.lock();
        while (!oddTurn) {
            try {
                // lock.wait();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + " " + i);
        oddTurn = false;
        // lock.notifyAll();
        condition.signalAll();
        lock.unlock();
    }

    // }

    private void printEven(int i) {
        // synchronized (lock) {
        lock.lock();
        while (oddTurn) {
            try {
                // lock.wait();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + " " + i);
        oddTurn = true;
        // lock.notifyAll();
        condition.signalAll();
        lock.unlock();
    }

    // }

    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        Thread odd = new Thread(new NumberPrinter("odd", lock, condition));
        Thread even = new Thread(new NumberPrinter("even", lock, condition));
        odd.start();
        even.start();
    }
}
0 голосов
/ 04 марта 2014

Вот мое решение без каких-либо ожиданий или уведомлений. wait () и notify () / notifyAll (),
Я не вижу причин использовать их для постановки этой проблемы.

package threading;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EvenOddPrinting {

    int count=0;
    boolean isOdd = false;

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        EvenOddPrinting obj = new EvenOddPrinting();
        exec.submit(new EvenPrinter(obj));
        exec.submit(new OddPrinter(obj));
        exec.shutdown();



    }

}

class EvenPrinter implements Runnable{
    EvenOddPrinting obj;
    public EvenPrinter(EvenOddPrinting obj) {
        this.obj=obj;
    }

    @Override
    public void run() {
        while(obj.count < 100){
            if(!obj.isOdd){
                System.out.println("Even:"+obj.count);
                obj.count++;
                obj.isOdd = true;
            }
        }

    }
}


class OddPrinter implements Runnable{

    EvenOddPrinting obj;
    public OddPrinter(EvenOddPrinting obj) {
        this.obj = obj;
    }

    @Override
    public void run() {
        while(obj.count < 100){
            if(obj.isOdd){
                System.out.println("Odd:"+obj.count);
                obj.count++;
                obj.isOdd = false;
            }
        }
    }
}
0 голосов
/ 15 марта 2013

i Использовал общий объект для управления порядком выполнения

class Counter implements Runnable {
  int count;
  static Class cl = Counter.class;

  public synchronized void increment() {
        String tname = Thread.currentThread().getName();
        System.out.printf("%s: %d\n", tname, count++);
  }

  @Override
  public void run() {
        String tname = Thread.currentThread().getName();
        while (true) {

              increment();
              synchronized (Counter.class) {
                    try {
                          cl.notify();
                          cl.wait();
                    } catch (Exception e) {
                          e.printStackTrace();
                    }
              }

        }
  }
}

public class WaitNotify {
public static void main(String[] args) {
    Counter c = new Counter();
    Thread t1 = new Thread(c, "thread1");
    Thread t2 = new Thread(c, "thread2");
    t1.start();
    t2.start();
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...