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) } 产生死锁问题
相关推荐
Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解
电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) OReilly.Java.Threads.3rd.Edition.Sep.2004.eBook-DDU Java Thread Programming (Sams) java线程第二版中英文 java线程第二版中英文 ...
Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...
Java线程Java线程Java线程Java线程Java线程Java线程
java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...
java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-...
Java线程基础教程完整版
Java线程模块Java线程之秒表新手学习Java线程模块时,利用Java中设置线程的暂停间隔,做的简易秒表
Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...
Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的统计信息,提供关于锁定监视器...
java线程同步java线程同步java线程同步
Java的线程和Java AppletJava的线程和Java AppletJava的线程和Java AppletJava的线程和Java AppletJava的线程和Java Applet
java线程.pdf java 学习java
java 线程 新手java 线程 新手java 线程 新手java 线程 新手
分析java线程日志的工具,使用jstack把java线程日志dump下来,然后上传到该工具,就可以查看线程阻塞情况等信息。
Java 模拟线程并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发
Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...
Java多线程读大文件 java多线程写文件:多线程往队列中写入数据