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