java 使用线程打印奇偶数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6017281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Odd even number printing using thread
提问by Sourabh
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.
谢谢你的帮助。
回答by aioobe
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
回答by Aaron Digulla
There are a lot of bugs in the code.
代码中有很多错误。
First of all, the synchronized
statements have no effect whatsoever. You create two thread instances, and each calls only its own methods. synchronized
is only useful if anotherthread can call a method.
首先,这些synchronized
声明没有任何影响。您创建了两个线程实例,每个实例只调用自己的方法。synchronized
仅当另一个线程可以调用方法时才有用。
Then notifyAll()
has no effect for the same reasons. odd.notifyAll()
doesn't reach even
hanging in the wait()
.
notifyAll()
由于相同的原因,然后没有影响。odd.notifyAll()
达不到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.
所以你需要的是另一个包含状态并且两个线程都可以看到和使用的对象。使用synchronized
,wait()
并notifyAll()
在第三个实例上。
回答by vijayinani
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();
}
}
回答by Jignesh
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();
}
}
回答by Jan Zyka
I think the problem might be that printOdd
and printEven
synchronize on different lock (the Thread's object instance locks). Therefor you have not guaranteed that the change on the static variable oddTurn
will be visible in the other thread. Try to make the oddTurn
volatile for the start.
我认为问题可能在于printOdd
并printEven
在不同的锁上同步(线程的对象实例锁)。因此,您不能保证静态变量的更改在oddTurn
其他线程中可见。尝试使oddTurn
开始变得不稳定。
回答by Vladimir Ivanov
You're missing volatile
keyword within oddTurn
variable. Without it there are no guarantees the threads see the actual value.
您volatile
在oddTurn
变量中缺少关键字。没有它就不能保证线程看到实际值。
回答by Dungeon Hunter
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();
}
}
回答by shreyas K N
Here's my solution without any waits or notify.
wait() and notify()/notifyAll() ,
I dont see any reason to use them for this problem statement.
这是我的解决方案,没有任何等待或通知。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;
}
}
}
}
回答by vijayinani
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();
}
}
回答by sanket patel
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