你理解下 public class TestDemo { public static void main(String[] args) { final Locker p = new Locker(); Task11 a = new Task11(p); Task21 b = new Task21(p); Task31 c = new Task31(p); Thread one = new Thread(a); one.start(); Thread two = new Thread(b); two.start(); // Thread three = new Thread(c); // three.start(); } }
class Task11 implements Runnable {
private Locker obj; public Task11(Locker p){ this.obj = p; }
我的粗浅看法: 楼主这样的逻辑,用while 好一些。看下面的代码:public class TestDemo {
public static void main(String[] args) { final Locker p = new Locker(); Task11 a = new Task11(p); Task21 b = new Task21(p); Task31 c = new Task31(p); Thread one = new Thread(a); one.start(); Thread two = new Thread(b); two.start(); Thread three = new Thread(c); three.start(); } }
class Task11 implements Runnable {
private Locker obj; public Task11(Locker p){ this.obj = p; }
class Locker { int num = 0; } 如果不用while, 需要这样改:public class TestDemo {
public static void main(String[] args) { final Locker p = new Locker(); Task11 a = new Task11(p); Task21 b = new Task21(p); Task31 c = new Task31(p); Thread one = new Thread(a); one.start(); Thread two = new Thread(b); two.start(); Thread three = new Thread(c); three.start(); } }
class Task11 implements Runnable {
private Locker obj; public Task11(Locker p){ this.obj = p; }
public class TestDemo {
public static void main(String[] args) {
final Locker p = new Locker();
Task11 a = new Task11(p);
Task21 b = new Task21(p);
Task31 c = new Task31(p);
Thread one = new Thread(a);
one.start();
Thread two = new Thread(b);
two.start();
// Thread three = new Thread(c);
// three.start();
}
}
class Task11 implements Runnable {
private Locker obj;
public Task11(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
if(obj.num != 0){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("a");
obj.num = 1;
obj.notifyAll();
}
}
}
}
}
class Task21 implements Runnable {
private Locker obj;
public Task21(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
if(obj.num != 1){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("b");
obj.num = 0;
obj.notifyAll();
}
}
}
}
} class Task31 implements Runnable {
private Locker obj;
public Task31(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
if(obj.num != 2){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("c");
obj.num = 0;
obj.notifyAll();
}
}
}
}
}
class Locker {
int num = 0;
}
楼主这样的逻辑,用while 好一些。看下面的代码:public class TestDemo {
public static void main(String[] args) {
final Locker p = new Locker();
Task11 a = new Task11(p);
Task21 b = new Task21(p);
Task31 c = new Task31(p);
Thread one = new Thread(a);
one.start();
Thread two = new Thread(b);
two.start();
Thread three = new Thread(c);
three.start();
}
}
class Task11 implements Runnable {
private Locker obj;
public Task11(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
while(obj.num != 0){//if 改成while,只要num != 0, 肯定等待。
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//必须num == 0 , 才执行。
System.out.println("a");
obj.num = 1;
obj.notifyAll();
}
}
}
}
class Task21 implements Runnable {
private Locker obj;
public Task21(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
while(obj.num != 1){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("b");
obj.num = 2;
obj.notifyAll();
}
}
}
}
class Task31 implements Runnable {
private Locker obj;
public Task31(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
while(obj.num != 2){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("c");
obj.num = 0;
obj.notifyAll();
}
}
}
}
class Locker {
int num = 0;
}
如果不用while, 需要这样改:public class TestDemo {
public static void main(String[] args) {
final Locker p = new Locker();
Task11 a = new Task11(p);
Task21 b = new Task21(p);
Task31 c = new Task31(p);
Thread one = new Thread(a);
one.start();
Thread two = new Thread(b);
two.start();
Thread three = new Thread(c);
three.start();
}
}
class Task11 implements Runnable {
private Locker obj;
public Task11(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
if(obj.num != 0){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒时判断num值,是0,执行输出;否则,本次唤醒无意义,需要把i减一,继续循环。而用while 就比较好。楼主试一下。
if(obj.num == 0){
System.out.println("a");
obj.num = 1;
obj.notifyAll();
}
else {
i--;
}
}
else {
System.out.println("a");
obj.num = 1;
obj.notifyAll();
}
}
}
}
}
class Task21 implements Runnable {
private Locker obj;
public Task21(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
if(obj.num != 1){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(obj.num == 1){
System.out.println("b");
obj.num = 2;
obj.notifyAll();
}
else {
i--;
}
}
else {
System.out.println("b");
obj.num = 2;
obj.notifyAll();
}
}
}
}
}
class Task31 implements Runnable {
private Locker obj;
public Task31(Locker p){
this.obj = p;
}
@Override
public void run() {
for(int i = 0; i < 5; i++){
synchronized (obj) {
if(obj.num != 2){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(obj.num == 2){
System.out.println("c");
obj.num = 0;
obj.notifyAll();
}
else {
i--;
}
}
else {
System.out.println("c");
obj.num = 0;
obj.notifyAll();
}
}
}
}
}
class Locker {
int num = 0;
}
for循环可能会执行到wait分支,故不可能打印所有的5个a(或者b,c)。
至于程序有时(占大比例)会停住,是因为比如task11已经跑完for循环,而此时task21,31均处于wait状态,没有地方触发notifyAll,所以会停住。解决方法:
问题关键点在于for循环的5次肯定不能输出五次a,b,c。
愚以为,作如下改动能实现楼主要求:
public class TestDemo { public static void main(String[] args) {
final Locker p = new Locker();
Task11 a = new Task11(p);
Task21 b = new Task21(p);
Task31 c = new Task31(p);
Thread one = new Thread(a, "Task11");
one.start();
Thread two = new Thread(b, "Task21");
two.start();
Thread three = new Thread(c, "Task31");
three.start();
}
}class Task11 implements Runnable { private Locker obj; public Task11(Locker p) {
this.obj = p;
} @Override
public void run() {
int i = 0;
while (true) {
synchronized (obj) {
if (obj.num != 0) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("a");
obj.num = 1;
obj.notifyAll();
if (4 == i++)
break;
}
}
}
}
}class Task21 implements Runnable { private Locker obj; public Task21(Locker p) {
this.obj = p;
} @Override
public void run() {
int i = 0;
while (true) {
synchronized (obj) {
if (obj.num != 1) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("b");
obj.num = 2;
obj.notifyAll();
if (4 == i++)
break;
}
}
}
}
}class Task31 implements Runnable { private Locker obj; public Task31(Locker p) {
this.obj = p;
} @Override
public void run() {
int i = 0;
while (true) {
synchronized (obj) {
if (obj.num != 2) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("c");
obj.num = 0;
obj.notifyAll();
if (4 == i++)
break;
}
}
}
}
}class Locker {
int num = 0;
}浅薄之见,还望指教。