奇数偶数打印使用thread.Create一个线程类,两个线程实例。一个将打印奇数,另一个将打印偶数。
我做了以下编码。但它涉及死锁状态。有人可以解释一下可能是什么原因吗?
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
然后陷入僵局!!!!!!
感谢您的帮助。
答案 0 :(得分:13)
您正在等待并通知不同的对象(监视器)。
我们的想法是,当您正在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
答案 1 :(得分:4)
代码中存在很多错误。
首先,synchronized
语句无效。您创建两个线程实例,每个实例只调用自己的方法。 synchronized
仅在另一个线程可以调用方法时才有用。
然后notifyAll()
因同样的原因无效。 odd.notifyAll()
even
未挂到wait()
。
所以你需要的是另一个包含状态的对象,两个线程都可以看到和使用它。在第三个实例上使用synchronized
,wait()
和notifyAll()
。
答案 2 :(得分:2)
使用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();
}
}
答案 3 :(得分:1)
我认为问题可能是printOdd
和printEven
在不同的锁(Thread的对象实例锁)上同步。因此,您无法保证静态变量oddTurn
的更改将在另一个线程中可见。尝试使oddTurn
易变为开始。
答案 4 :(得分:1)
我这样做了
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();
}
}
答案 5 :(得分:0)
volatile
变量中缺少oddTurn
个关键字。没有它,就无法保证线程看到实际值。
答案 6 :(得分:0)
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();
}
}
答案 7 :(得分:0)
这是我的解决方案,没有任何等待或通知。
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;
}
}
}
}
答案 8 :(得分:0)
使用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();
}
}
答案 9 :(得分:0)
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();
}
}
奇数线程1
连线程2
奇数话题3
连线程4
奇数线程5
答案 10 :(得分:0)
我已经以这样的方式实现了,基于这个参数,不会产生任何线程,并且会以循环方式相应的no。 即,如果线程数为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();
}
}
}
答案 11 :(得分:0)
两个线程的程序,交替打印奇数和偶数。
#使用“对象锁定”概念实现。
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");
}
}
答案 12 :(得分:0)
我以一种非常简单的方式(从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();
}
}