Java 用螺纹印刷奇偶数

Java 用螺纹印刷奇偶数,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,使用线程打印奇偶数。创建一个线程类,两个线程实例。一个将打印奇数,另一个将打印偶数。 我做了如下的编码。但到了死锁状态。有人能解释一下原因吗 public class NumberPrinter implements Runnable{ private String type; private static boolean oddTurn=true; public NumberPrinter(String type){ this.type=type; } public void ru

使用线程打印奇偶数。创建一个线程类,两个线程实例。一个将打印奇数,另一个将打印偶数。

我做了如下的编码。但到了死锁状态。有人能解释一下原因吗

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

}
}
公共类NumberInter实现可运行{
私有字符串类型;
私有静态布尔值oddTurn=true;
public numberprint(字符串类型){
this.type=type;
}
公开募捐{
int i=类型等于(“奇数”)?1:2;

而(i您在
oddTurn
变量中缺少
volatile
关键字。没有它,就不能保证线程看到实际值。

我认为问题可能是
printOdd
print偶数
在不同的锁上同步(线程的对象实例锁)因此,您无法保证静态变量
oddTurn
的更改在另一个线程中可见。请尝试在开始时使
oddTurn
不稳定。

您正在等待并通知不同的对象(监视器)

其思想是,您可以调用
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();                        // <-------
    }
}
输出:

odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9
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();
    }
}

代码中有很多错误

首先,
synchronized
语句没有任何效果。您创建两个线程实例,每个实例只调用自己的方法。
synchronized
仅在另一个线程可以调用方法时才有用

然后,由于同样的原因,
notifyAll()
无效。
odd.notifyAll()
未达到
偶数
挂起在
wait()

因此,您需要的是另一个包含状态的对象,并且两个线程都可以看到和使用它。在第三个实例上使用
synchronized
wait()
notifyAll()

我就是这样做的

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();
        }           
}
公共类奇偶校验{
公共静态void main(字符串[]args){
打印o=新打印();
线程偶数=新线程(新MyRunnable(2,o));
线程奇数=新线程(新MyRunnable(1,o));
偶数。开始();
奇。开始();
}
}
类MyRunnable实现Runnable{
int启动;
打印ob;
MyRunnable(整数s,打印o){
开始=秒;
ob=o;
}
公开募捐{

对于(inti=start;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();
}
}

这是我的解决方案,没有任何等待或通知。 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;
            }
        }
    }
}
包线程;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公共类印刷{
整数计数=0;
布尔值isOdd=false;
公共静态void main(字符串[]args){
ExecutorService exec=Executors.newCachedThreadPool();
EvenOddPrinting obj=新EvenOddPrinting();
执行提交(新打印机(obj));
执行提交(新打印机(obj));
exec.shutdown();
}
}
类实现可运行的{
均匀印刷体;
公用打印机(EvenOddPrinting obj){
obj=obj;
}
@凌驾
公开募捐{
而(对象计数<100){
如果(!obj.isOdd){
System.out.println(“偶数:+obj.count”);
obj.count++;
obj.isOdd=真;
}
}
}
}
类实现可运行的{
均匀印刷体;
公用打印机(EvenOddPrinting obj){
this.obj=obj;
}
@凌驾
公开募捐{
而(对象计数<100){
if(目标isOdd){
System.out.println(“奇数:+obj.count”);
obj.count++;
obj.isOdd=假;
}
}
}
}

同样的问题可以通过锁接口解决:

odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9
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();
    }
}
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();
    }
}
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();
    }
}
import java.util.concurrent.ThreadLocalRandom;
导入java.util.concurrent.locks.Condition;
导入java.util.concurrent.locks.Lock;
公共类OddNumberLock实现Runnable{
自然领主自然领主;
锁;
条件;
公共OddNumberLock(自然领主,自然领主,锁,条件){
this.naturalOrder=naturalOrder;
this.lock=锁;
这个条件=条件;
}
@凌驾
公开募捐{
lock.lock();
while(naturalOrder.currentNumber<20){
while(naturalOrder.evenOdd!=false){
试一试{
条件wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
试一试{
sleep(ThreadLocalRandom.current().nextInt(1000));
}捕捉(中断异常e){
e、 printStackTrace();
}
如果(naturalOrder.currentNumber%2!=0){
System.out.println(naturalOrder.currentNumber);
}
naturalOrder.currentNumber++;
naturalOrder.evenOdd=true;
条件.signalAll();
}
lock.unlock();
}
}
EvenNumberLock.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();
    }
}
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();
    }
}
import java.util.concurrent.ThreadLocalRandom;
导入java.util.concurrent.locks.Condition;
导入java.util.concurrent.locks.Lock;
公共类EvenNumberLock实现Runnable{
自然领主自然领主;
锁;
条件;
公共偶数锁(自然领主、自然领主、锁、条件){
this.naturalOrder=naturalOrder;
this.lock=锁;
这个条件=条件;
}
@凌驾
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();
    }
}