当时没有答好回来总结一下总结了两个方式
一,这个方式是利用Object.notify(),Object.wait(),两个方法来实现。
中心思想:保证应该到哪个线程打印时,只有该线程是唤醒状态,其他都是暂停状态。比如需要P1打印1,那就要让P2,P3都是wait()状态。
package com.example.ly.mydemo;
public class WaitObjectTest implements Runnable {
private static int i = 0;
private Object selfO = null;
private Object pref = null;
public WaitObjectTest(Object selfO, Object pref) {
this.selfO = selfO;
this.pref = pref;
}
@Override
public void run() {
System.out.println("threadId: " + Thread.currentThread().getName());
while (i < 30) {
synchronized (pref) {
synchronized (selfO) {
System.out.println("threadId: " + Thread.currentThread().getName() + " i: " + i);
i++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
selfO.notify();
}
try {
pref.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
int[] object1 = new int[0];
int[] object2 = new int[0];
int[] object3 = new int[0];
WaitObjectTest mRunnableA = new WaitObjectTest(object1, object3);
WaitObjectTest mRunnableB = new WaitObjectTest(object2, object1);
WaitObjectTest mRunnableC = new WaitObjectTest(object3, object2);
Thread threadA = new Thread(mRunnableA, "A");
Thread threadB = new Thread(mRunnableB, "B");
Thread threadC = new Thread(mRunnableC, "C");
threadA.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadB.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadC.start();
}
}
二,这个方式我和朋友一个完善的一个方法,中心思想是:只synchronized数组,用循环来控制打印,就是打印需要的不需要的就continue。
class A implements Runnable {
Thread p1, p2, p3;
int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8,9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
int count = 0;
public A() {
p1 = new Thread(this,"0");
p2 = new Thread(this,"1");
p3 = new Thread(this,"2");
p1.start();
p2.start();
p3.start();
}
@Override
public void run() {
while (count < arr.length) {
synchronized (arr) {
String threadName = Thread.currentThread().getName();
if (count % 3 == Integer.valueOf(threadName)) {
LogUtils.writeLog("p:" + (Integer.valueOf(threadName)+1) + "=" + arr[count]);
count++;
} else {
continue;
}
}
}
}
}
总结:
1.第一个方法是朋友提供的,其实我不是很喜欢代码多,可读性差,但是第一个种方法可以帮助理解线程同步的原理,所以也贴出来大家一起学习一下。
2.第二种方法是我跟朋友一起总结出来的。是我自己觉得比较好的方式,毕竟核心代码比较少,而且满足了需求。
3.线程同步主要是synchronized关键字来控制访问,必要时配合Object的Object.notify(),Object.wait(),两个方法,实际上Java还提供了专门针对线程同步问题的类,回头再针对线程同步问题做一篇总结吧。