简体   繁体   English

使用线程打印奇偶数

[英]Odd even number printing using thread

Odd even number printing using thread.Create one thread class, two instance of the thread.使用线程打印奇偶数。创建一个线程类,两个线程实例。 One will print the odd number and the other will print the even number.一个将打印奇数,另一个将打印偶数。

I did the following coding.我做了以下编码。 But it comes to dead lock state.但涉及到死锁状态。 Can some one please explain what might be the reason for that?有人可以解释一下可能是什么原因吗?

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输出: odd1 even2


then comes to deadlock!!!!!!然后陷入僵局!!!!!!

Thanks for your help.谢谢你的帮助。

You're waiting and notifying different objects ( monitors ).您正在等待并通知不同的对象(监视器)。

The idea is that you can call obj.wait() to wait for someone to do obj.notify() , while you're doing objA.wait() and objB.notify() .这个想法是你可以调用obj.wait()来等待某人做obj.notify() ,而你正在做objA.wait()objB.notify()

Change your printOdd method to something like将您的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();                        // <-------
    }
}

and the printEven method similarly.printEven方法类似。

Then provide the NumberPrinter with a lock object:然后为NumberPrinter提供一个lock对象:

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

Output:输出:

odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9

There are a lot of bugs in the code.代码中有很多错误。

First of all, the synchronized statements have no effect whatsoever.首先, synchronized语句没有任何作用。 You create two thread instances, and each calls only its own methods.您创建了两个线程实例,每个实例只调用自己的方法。 synchronized is only useful if another thread can call a method. synchronized只有在另一个线程可以调用方法时才有用。

Then notifyAll() has no effect for the same reasons.由于同样的原因, notifyAll()无效。 odd.notifyAll() doesn't reach even hanging in the wait() . odd.notifyAll() even没有达到even挂在wait()

So what you need is another object which contains the state and which both threads can see and use.所以你需要的是另一个包含状态并且两个线程都可以看到和使用的对象。 Use synchronized , wait() and notifyAll() on that third instance.在第三个实例上使用synchronizedwait()notifyAll()

The same can be solved using Lock interface:使用 Lock 接口也可以解决同样的问题:

NaturalOrder.java自然顺序.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奇数锁.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偶数锁.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();
    }
}

I did this way我是这样做的

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();
        }           
}

I think the problem might be that printOdd and printEven synchronize on different lock (the Thread's object instance locks).我认为问题可能是printOddprintEven在不同的锁上同步(线程的对象实例锁)。 Therefor you have not guaranteed that the change on the static variable oddTurn will be visible in the other thread.因此,您不能保证静态变量oddTurn上的更改将在另一个线程中可见。 Try to make the oddTurn volatile for the start.尝试在开始时使oddTurn不稳定。

i Used a shared object to control the order of execution 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();
}
}

Here's my solution without any waits or notify.这是我的解决方案,没有任何等待或通知。 wait() and notify()/notifyAll() , wait() 和 notify()/notifyAll() ,
I dont see any reason to use them for this problem statement.我看不出有任何理由在这个问题陈述中使用它们。

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;
            }
        }
    }
}

Your code corrected with using Lock interface:使用 Lock 界面更正了您的代码:

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();
    }
}
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();

 }

}

output for limit 5:限制 5 的输出:

enter limit: 5输入限制:5

odd thread 1奇数线程 1

even thread 2偶数2

odd thread 3奇怪的线程 3

even thread 4连线 4

odd thread 5奇数线程 5

I have implemented in such a way, based on the argument, no of threads will be spawned and will the respective no in round robin manner.我已经以这种方式实现,根据论点,不会产生任何线程,并且不会以循环方式产生相应的线程。 ie, If thread count is 3, thread 1 will print 1,4 ...;即,如果线程数为 3,线程 1 将打印 1,4 ...; thread 2 will print 2,5,... and thread 3 will print 3,6...线程 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();
    }

    }

}

You're missing volatile keyword within oddTurn variable.您在oddTurn变量中缺少volatile关键字。 Without it there are no guarantees the threads see the actual value.没有它,就不能保证线程看到实际值。

Program for Two Threads Alternatively Print Odd and Even Numbers.两个线程的程序或者打印奇数和偶数。

#Implemented Using "Object Lock" Concept. #使用“对象锁”概念实现。

class Increment{
private int count;
    public void increment(){
        count++;
        System.out.println(Thread.currentThread().getName()+"::::::::::::::::::"+count);
    }
}


class SimpleThread extends Thread{
 
 Increment obj = null;
 
 SimpleThread(Increment obj){
    this.obj=obj;
 }  
 
 public void run(){
     try {
    Thread.sleep(100);
         while(true){
            synchronized(obj){
                   obj.increment();
                   Thread.sleep(1000);
                   obj.notify();
                   obj.wait();  
            }
         }
     } catch(InterruptedException ie) {
        ie.printStackTrace(); 
     }
 } 
 
}

public class Main
{
    public static void main(String[] args) {
        
        Increment increment = new Increment();
        SimpleThread t1 = new SimpleThread(increment);
        SimpleThread t2 = new SimpleThread(increment);
       
        t1.start();
        t2.start();

        System.out.println(Thread.currentThread().getName()+"::::::::::::::"+"Hello World");
        System.out.println(Runtime.getRuntime().availableProcessors()+"::::::::::::::"+"CORE SIZE");
    }
}

I implemented it in a very simple way, from 1 to 40>我用很简单的方式实现了,从1到40>

public class EvenOddProblem {

    public static void main(String[] args) {
        Printer p = new Printer();
        EvenThread enenThread = new EvenThread(p);
        OddThread oddThread = new OddThread(p);
        new Thread(enenThread).start();
        new Thread(oddThread).start();

    }

}

class EvenThread implements Runnable {
    private Printer printer;

    public EvenThread(Printer p) {
        printer = p;
    }

    @Override
    public void run() {
        try {
            int i = 0;
            while (true) {
                if (i == 20)
                    break;
                i++;

                printer.evenPrintEven();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class OddThread implements Runnable {
    private Printer printer;

    public OddThread(Printer p) {
        printer = p;
    }

    @Override
    public void run() {
        int i = 0;
        try {
            while (true) {
                if (i == 20)
                    break;
                i++;
                printer.evenPrintOdd();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class Printer {
    private static volatile Integer i = 1;

    public synchronized void evenPrintOdd() throws InterruptedException {
        while (i % 2 == 0) {
            wait();
        }
        System.out.println(i);
        i++;
        notifyAll();
    }

    public synchronized void evenPrintEven() throws InterruptedException {
        while (!(i % 2 == 0)) {
            wait();
        }
        System.out.println(i);
        i++;
        notifyAll();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM