题目
使用生产者和消费者模式实现,交替输出:
假设只有两个线程,输出以下结果:
t1-->1
t2-->2
t1-->3
t2-->4
t1-->5
t2-->6
....
要求:必须交替,并且t1线程负责输出奇数。t2线程负责输出偶数。
两个线程共享一个数字,每个线程执行时都要对这个数字进行:++
代码
一开始采用的Integer类型:
public class Homework1 {
public static void main(String[] args)throws Exception {
Integer integer=new Integer(0);
Thread t1=new Thread(new SCZ(integer));
Thread t2=new Thread(new XFZ(integer));
t1.setName("t1");
t2.setName("t2");
t1.start();
Thread.sleep(1);
t2.start();
}
}
class SCZ implements Runnable {
public static Integer integer;
public SCZ() {
}
public SCZ(Integer integer) {
this.integer = integer;
}
@Override
public void run() {
while (true){
synchronized (integer) {
//停止生产的条件
System.out.println(System.identityHashCode(integer));//402421002
if (integer % 2 == 1) {
try {
integer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
integer=integer+1;
System.out.println(Thread.currentThread().getName() + "-->" + integer);
System.out.println(System.identityHashCode(integer));//423332229
integer.notifyAll();
}
}
}
}
class XFZ implements Runnable{
public static Integer integer;
public XFZ() {
}
public XFZ(Integer integer) {
this.integer = integer;
}
@Override
public void run() {
while (true){
synchronized (integer) {
System.out.println(System.identityHashCode(integer));//402421002
//停止消费的条件
if (integer % 2 == 0) {
try {
integer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
integer=integer+1;
System.out.println(Thread.currentThread().getName() + "-->" + integer);
integer.notify();
}
}
}
}
报错如下:
后来尝试输出生产者和消费者的实际地址,发现一致。输出生产者加1后的实际地址,发现此时的integer对象地址已经发生改变,而消费者拿到的是之前的地址,因此唤醒和等待对象的内存地址不一致,唤了个寂寞。
后来尝试了创建Num类,使用成员变量记录数据,锁num对象,没有问题。
public class Homework2 {
public static void main(String[] args) {
Num num=new Num(0);
Thread t1=new Thread(new SCZ(num));
Thread t2=new Thread(new XFZ(num));
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
class Num{
int i;
public Num() {
}
public Num(int i) {
this.i = i;
}
}
class SCZ implements Runnable {
private Num num;
public SCZ() {
}
public SCZ(Num num) {
this.num = num;
}
@Override
public void run() {
while (true){
synchronized (num) {
//停止生产的条件
if (num.i % 2 == 1) {
try {
num.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num.i++;
System.out.println(Thread.currentThread().getName() + "-->" + num.i);
num.notify();
}
}
}
}
class XFZ implements Runnable{
private Num num;
public XFZ() {
}
public XFZ(Num num) {
this.num = num;
}
@Override
public void run() {
while (true){
synchronized (num) {
//停止生产的条件
if (num.i % 2 == 0) {
try {
num.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num.i++;
System.out.println(Thread.currentThread().getName() + "-->" + num.i);
num.notify();
}
}
}
}
输出如下:
总结
基本数据类型的包装类不适合作为锁,尽量不要使用。