當時沒有答好回來總結一下總結了兩個方式
一,這個方式是利用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還提供了專門針對線程同步問題的類,回頭再針對線程同步問題做一篇總結吧。