Java多线程状态图
Java多线程状态图一:
Java多线程状态图二:
Java线程状态3
线程阻塞的原因:
1.IO阻塞,比如线程状态一种的Blocked
2.线程互斥导致的阻塞,比如尝试获得一个对象锁,而这个锁被其它对象持有,那么这个线程只能等待。 一个对象可以有多个线程等待获得它的锁,因此,这里有一个对象锁池的概念(Lock Pool)。当持有锁的线程释放锁后,默认情况下,其它线程竞争这个把锁,究竟哪个线程获得这个锁,是与CPU调度有关的。如果要获得先等待先获得的这种公平锁,需要使用JUC提供的锁,比如ReentrantLock
3.线程同步导致的阻塞,比如一个线程只能等到它等待的事件发生了(wait/notify/notifyAll),这个线程才能恢复到可运行态。
wait/notify示例---生产者消费者问题
不优雅的做法:
当plates对象执行notifyAll动作时,不管是消费线程和生产线程都被唤醒了。事实上,在调用notifyAll时,上下文能够确定是消费者消费了之后唤醒生产者线程可以继续生产了,还是生产者生产了之后唤醒消费者线程继续消费。
import java.util.*;
public class WaitAndNotifyTest {
private static volatile boolean shutdown = false;
public static void main(String[] args) {
final Queue<Integer> plates = new LinkedList<Integer>();
Thread[] consumers = new Thread[3];
for (int i = 0; i < consumers.length; i++) {
consumers[i] = new Thread() {
@Override
public void run() {
while (!shutdown) {
synchronized (plates) {
while (plates.size() <= 0) {
try {
plates.wait();
} catch (InterruptedException e) {
}
}
if (plates.size() > 0) {
System.out.println(plates.poll() + " is consumed");
plates.notifyAll(); //唤醒所有的线程,不管是生产者还是消费者,因为它们都同步于plates对象锁
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
consumers[i].start();
}
Thread[] producers = new Thread[5];
for (int i = 0; i < producers.length; i++) {
producers[i] = new Thread() {
@Override
public void run() {
while (!shutdown) {
synchronized (plates) {
while (plates.size() == 10) {
try {
plates.wait();
} catch (InterruptedException e) {
}
}
if (plates.size() < 10) {
int i = new Random().nextInt();
plates.offer(i);
plates.notifyAll(); //唤醒所有的线程,不管是生产者还是消费者,因为它们都同步于plates对象锁
System.out.println(i + " is put into the plate");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
producers[i].start();
}
try {
Thread.sleep(6000);
shutdown = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
错误的做法一:
下面的代码生产和消费使用了两把锁,但是应该是有问题的。这应该是JUC的多路条件等待要解决的事情!!
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ThreadLocalRandom;
class Plate<T> {
private final Object PLATE_NOT_FULL = new Object();
private final Object PLATE_NOT_EMPTY = new Object();
private final Queue<T> plates = new LinkedList<T>();
private int size;
public Plate(int size) {
this.size = size;
}
public void produce(T fruit) {
synchronized (PLATE_NOT_FULL) {
if (plates.size() >= size) {
try {
System.out.println(Thread.currentThread().getName() + ", The plate is full..waiting to put into the plate");
PLATE_NOT_FULL.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (PLATE_NOT_EMPTY) {
if (plates.size() < size) { //程序运行到这里,有可能plates已经满了,因此,这个操作不会将fruit加入到盘子中,也就是说,调用produce方法的线程丢失了本次生产的fruit
plates.offer(fruit);
System.out.println(Thread.currentThread().getName() + ", The plate is not full..put the fruit into the plate," + fruit);
PLATE_NOT_EMPTY.notifyAll();
}
}
}
public T consume() {
T fruit = null;
synchronized (PLATE_NOT_EMPTY) {
if (plates.size() <= 0) {
try {
System.out.println(Thread.currentThread().getName() + ", The plate is empty..waiting to consume");
PLATE_NOT_EMPTY.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (PLATE_NOT_FULL) {
if (plates.size() > 0) { //Safe guard
fruit = plates.poll();
System.out.println(Thread.currentThread().getName() + ", The plate is not empty..consume" + fruit);
PLATE_NOT_FULL.notifyAll();
return fruit;
}
}
return fruit;
}
}
public class ThreadCommunication {
private static volatile boolean shutdown = false;
public static void main(String[] args) {
final Plate<Integer> plate = new Plate<Integer>(8);
Thread[] consumers = new Thread[5];
for (int i = 0; i < consumers.length; i++) {
consumers[i] = new Thread() {
@Override
public void run() {
while (!shutdown) {
plate.consume();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
consumers[i].start();
}
Thread[] producers = new Thread[5];
for (int i = 0; i < producers.length; i++) {
producers[i] = new Thread() {
@Override
public void run() {
while (!shutdown) {
plate.produce(ThreadLocalRandom.current().nextInt(100, 1000));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
producers[i].start();
}
try {
Thread.sleep(6000);
shutdown = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
错误做法二:线程死锁
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ThreadLocalRandom;
class Plate<T> {
private final Object PLATE_NOT_FULL = new Object();
private final Object PLATE_NOT_EMPTY = new Object();
private final Queue<T> plates = new LinkedList<T>();
private int size;
public Plate(int size) {
this.size = size;
}
public void produce(T fruit) {
synchronized (PLATE_NOT_FULL) {
if (plates.size() >= size) {
try {
System.out.println(Thread.currentThread().getName() + ", The plate is full..waiting to put into the plate");
PLATE_NOT_FULL.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (PLATE_NOT_EMPTY) {
if (plates.size() < size) { //Safe guard
plates.offer(fruit);
System.out.println(Thread.currentThread().getName() + ", The plate is not full..put the fruit into the plate," + fruit);
PLATE_NOT_EMPTY.notifyAll();
}
}
}
}
public T consume() {
T fruit = null;
synchronized (PLATE_NOT_EMPTY) {
if (plates.size() <= 0) {
try {
System.out.println(Thread.currentThread().getName() + ", The plate is empty..waiting to consume");
PLATE_NOT_EMPTY.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (PLATE_NOT_FULL) {
if (plates.size() > 0) { //Safe guard
fruit = plates.poll();
System.out.println(Thread.currentThread().getName() + ", The plate is not empty..consume" + fruit);
PLATE_NOT_FULL.notifyAll();
return fruit;
}
}
}
return fruit;
}
}
public class ThreadCommunication {
private static volatile boolean shutdown = false;
public static void main(String[] args) {
final Plate<Integer> plate = new Plate<Integer>(8);
Thread[] consumers = new Thread[5];
for (int i = 0; i < consumers.length; i++) {
consumers[i] = new Thread() {
@Override
public void run() {
while (!shutdown) {
plate.consume();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
consumers[i].start();
}
Thread[] producers = new Thread[5];
for (int i = 0; i < producers.length; i++) {
producers[i] = new Thread() {
@Override
public void run() {
while (!shutdown) {
plate.produce(ThreadLocalRandom.current().nextInt(100, 1000));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
producers[i].start();
}
try {
Thread.sleep(6000);
shutdown = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
典型的:
synchronized(A) {
synchronized(B)
}
和
synchronized(B) {
synchronized(A)
}
产生死锁问题