使用线程奇数偶数打印
奇数偶数打印使用线程。创build一个线程类,线程的两个实例。 一个会打印奇数,另一个会打印偶数。
我做了以下编码。 但是到了死锁状态。 有人可以解释一下可能的原因吗?
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(); } }
输出: odd1 even2
然后来到僵局!!!!!!
谢谢你的帮助。
您正在等待并通知不同的对象( 监视器 )。
这个想法是,当你在做objA.wait()
和objB.notify()
,你可以调用obj.wait()
来等待某个人做objB.notify()
。
把你的printOdd
方法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
代码中有很多错误。
首先, synchronized
声明没有任何影响。 你创build两个线程实例,每个线程只调用自己的方法。 synchronized
只有在另一个线程可以调用方法时才有用。
那么notifyAll()
由于相同的原因不起作用。 odd.notifyAll()
even
不会挂在wait()
。
所以你需要的是另一个包含状态的对象,这两个线程都可以看到和使用。 在第三个实例上使用synchronized
, wait()
和notifyAll()
。
同样可以使用Lock界面来解决:
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(); } }
我认为问题可能是printOdd
和printEven
同步在不同的锁(线程的对象实例锁)。 因此,您不能保证在其他线程中可以看到静态variablesoddTurn
的变化。 尝试使oddTurn
不稳定。
我是这样做的
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(); } }
您在oddTurn
variables中缺lessvolatile
关键字。 没有它,没有保证线程看到的实际价值。
我使用共享对象来控制执行的顺序
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(); } }
这是我的解决scheme,没有任何等待或通知。 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; } } } }
使用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(); } }
输出限制5:
input限制:5
奇怪的线程1
甚至是线程2
奇怪的线程3
甚至是线程4
奇怪的线程5
我已经以这样的方式实施了,根据这个论点,没有任何线程会被产生,并且会以循环方式分别产生。 即如果线程数为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(); } } }