問題
使用 wait notify 實現一個隊列,隊列有2個方法,add 和 get 。add方法往隊列中添加元素,get方法往隊列中獲得元素。隊列必須是線程安全的。如果get執行時,隊列爲空,線程必須阻塞等待,直到有隊列有數據。如果add時,隊列已經滿,則add線程要等待,直到隊列有空閒空間。
答案
//這是一段錯誤的實現代碼
package java併發學習.自己實現線程安全的隊列;
import java.util.LinkedList;
/**
* Created by h on 17-2-2.
*/
class MyQueue {
int sum = 100;
LinkedList<Integer> lls = new LinkedList<>();
public Integer get() {
if (lls.size() > 0) {
int res = lls.get(0);
lls.remove(0);
return res;
} else return -1;
}
public void put(int i) {
lls.add(lls.size(), i);
}
}
public class Main {
public static void main(String[] args) {
MyQueue q = new MyQueue();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
if (q.lls.size() < 100)
q.put(i);
System.out.println("PUT " + i);
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
if (q.lls.size() > 0)
System.out.println("GET " + q.get());
}
}
});
t1.start();
t2.start();
}
}
解法
package java併發學習.自己實現線程安全的隊列;
import java.util.LinkedList;
/**
* Created by h on 17-2-2.
*/
class MyQueue {
int sum = 100;
LinkedList<Integer> lls = new LinkedList<>();
public Integer get() {
synchronized (lls) {
while (lls.size()<=0){
try {
lls.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lls.notify();
}
return lls.remove(0);
}
public void put(int i) {
synchronized (lls){
while (lls.size() >= sum){
try {
lls.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lls.notify();
lls.add(i);
System.out.println("put " + i);
}
}
}
public class Main {
public static void main(String[] args) {
MyQueue q = new MyQueue();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println("get " + q.get());
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
q.put(i);
}
}
});
t1.start();
t2.start();
}
}