目录
使用wait和notify实现生产者消费者
public class Main2 {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
int MAX = 5;//生产商品总数
Thread t1 = new Thread(){
public void run(){
while ( true ) {
synchronized (list) {//加锁
while ( list.size() == MAX ) {
try {
list.wait();//如果生产商品数目大于生产商品最大值,那么释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int num = (int) (Math.random() * 100);
list.add(num);
System.out.println(Thread.currentThread().getName() + "---" + num);
list.notify();//唤醒消费者线程,只有当前线程释放锁后才能被唤醒
}
}
}
};
Thread t2 = new Thread(){
public void run(){
while ( true ) {
synchronized (list) {//加锁
while ( list.size() == 0 ) {//消费完队列中商品进行等待
try {
list.wait();//等待释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int num = list.pop();//队列中有商品,进行消费
System.out.println(Thread.currentThread().getName() + "---" + num);
list.notify();//唤醒生产者线程,只有当前线程释放锁后才能被唤醒
}
}
}
};
t1.start();
t2.start();
}
}
使用阻塞队列来实现生产者消费者模式
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
/**
* Created by Hollake on 2019\8\14 0014 15:31.
*/
public class BlockingQueueTest {
public static void main(String[] args) {
BlockingDeque<Integer> queue = new LinkedBlockingDeque<>(5);
Thread t1 = new Thread(){
public void run(){
while ( true ) {
int temp = (int) (Math.random() * 100);
try {
queue.put(temp);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "----" + temp);
}
}
};
Thread t2 = new Thread(){
public void run(){
while ( true ) {
try {
int res = queue.take();
System.out.println(Thread.currentThread().getName() + "----" + res);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
t2.start();
}
}
两线程交替打印AB
public class Main2 {
static boolean flag = false;
public static void main(String[] args) {
Object LOCK = new Object();
Thread t1 = new Thread(){
public void run(){
while ( true ) {
synchronized (LOCK) {//加锁
while ( flag ) {
try {
LOCK.wait();//满足条件就释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "---" + "A");
flag = true;
LOCK.notify();//唤醒另外一个线程,只有当前线程释放锁后才能被唤醒
}
}
}
};
Thread t2 = new Thread(){
public void run(){
while ( true ) {
synchronized (LOCK) {//加锁
while ( !flag ) {
try {
LOCK.wait();//等待释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "---" + "B");
flag = false;
LOCK.notify();//唤醒生产者线程,只有当前线程释放锁后才能被唤醒
}
}
}
};
t1.start();
t2.start();
}
}
简单死锁例子
package arithmetic;
/**
* Created by Hollake on 2019\7\17 0017 22:08.
*/
public class Main2 {
static boolean flag = false;
public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
Thread t1 = new Thread(){
public void run(){
synchronized (a) {//加锁
try {
Thread.sleep(20);//必须进行睡眠等待,不睡眠等待可以,但是一般不会发生死锁,因为程序执行太快
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {//拿到a锁的情况下还想拿到b锁,这与另外一个线程情况正好相反,
// 持有资源,不释放资源,还需要其他线程持有的资源,死锁的条件
System.out.println("不会执行到这里");
}
}
}
};
Thread t2 = new Thread(){
public void run(){
synchronized (b) {//加锁
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a) {
System.out.println("不会执行到这里");
}
}
}
};
t1.start();
t2.start();
}
}
这个也是交替打印AB
package arithmetic;
import java.util.LinkedList;
/**
* Created by Hollake on 2019\6\24 0024 20:41.
*/
public class SwapPrint {
public static void main(String[] args) throws InterruptedException {
LinkedList<String> list = new LinkedList<>();
list.add("A");
list.add("B");
list.add("A");
list.add("B");
Object a = new Object();
Object b = new Object();
MyThread myThread1 = new MyThread(b,a,list);
MyThread myThread2 = new MyThread(a,b,list);
(new Thread(myThread1)).start();
Thread.sleep(100);
(new Thread(myThread2)).start();
}
}
class MyThread implements Runnable {
private LinkedList<String> list;
private Object pre;
private Object self;
public MyThread( Object pre, Object self,LinkedList<String> list) {
this.self = self;
this.pre = pre;
this.list = list;
}
@Override
public void run() {
while ( !list.isEmpty() ){
synchronized (pre) {//先拿到前一个线程的锁
synchronized (self) {//接着拿到自己的锁
System.out.println(Thread.currentThread() + list.poll());
self.notify();//唤醒另外一个线程
}
try {
pre.wait();//释放前一个线程的锁,中止当前线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
交替打印字符串,例如:hello world
import java.util.LinkedList;
/**
* Created by Hollake on 2019\7\17 0017 22:08.
*/
public class Main2 {
static boolean flag = false;
static String str = "HELLO WORLD";
static int max = str.length();
public static void main(String[] args) {
Object LOCK = new Object();
LinkedList<String> list = new LinkedList<>();
for (int i = 0; i < max; i++) {
list.add(String.valueOf(str.charAt(i)));
}
Thread t1 = new Thread(){
public void run(){
while ( max > 0 ) {
synchronized (list) {//加锁
while ( flag ) {
try {
list.wait();//满足条件就释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//在这里为什儿要进行list是否为null的判断呢,仔细思考一下,如果不判断,例如打印两个字母ab,
// 第一次线程t1打印a后,继续到try中,调用list.wait()方法,释放锁,线程t2拿到锁,继续打印b,
// 接着同样的释放锁,线程t1从try中的wait()方法中被唤醒,继续执行,但是list中已经没有了元素,
// 所以调用pop()方法直接会抛出空指针异常
if (list.size() > 0) {
System.out.println(Thread.currentThread().getName() + "---" + list.pop());
}
max--;
flag = true;
list.notify();//唤醒t2线程,只有当前线程释放锁后才能被唤醒
}
}
}
};
Thread t2 = new Thread(){
public void run(){
while ( max > 0 ) {
synchronized (list) {//加锁
while ( !flag ) {
try {
list.wait();//释放锁等待被唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (list.size() > 0) {
System.out.println(Thread.currentThread().getName() + "---" + list.pop());
}
max--;
flag = false;
list.notify();//唤醒t1线程,只有当前线程释放锁后才能被唤醒
}
}
}
};
t1.start();
t2.start();
}
}