public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
1、NEW
新创建线程,还没调用start方法,此时线程处于New的状态
Thread thread= new Thread(new Runnable() {
@Override
public void run() {
testConsume();
}
});
Log.d(TAG, "onCreate1: state="+thread.getState());
此时log打印:
onCreate1: state=NEW
2、RUNNABLE
调用了start方法就可以在java虚拟机中执行了,但是可能并没有在操作系统中运行,因为此时可能缺少CPU资源。
Thread thread= new Thread(new Runnable() {
@Override
public void run() {
testConsume();
}
});
Log.d(TAG, "onCreate1: state="+thread.getState());
thread.start();
Log.d(TAG, "onCreate2: state="+thread.getState());
此时log打印:
onCreate1: state=NEW
onCreate2: state=RUNNABLE
3、BLOCKED
进入synchronized 代码块但是没有获取到锁对象,可能是首次进入synchronized 代码块也可能是之前进入synchronized代码块使用wait等待又被唤醒再次进入synchronized代码块。
4、WAITING
由于线程调用了无时间参数的Object#wait()、Thread.join、LockSupport.park中的某个方法使得线程处于等待状态,此时线程等待其他线程的特定动作,比如Object.wait()等待其他线程调用Object.notify()或Object.notifyAll();Thread.join()等待另外的线程执行完;
5、TIMED_WAITING
等待特定时间,当调用带时间参数的这些方法Thread.sleep、Object.wait、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil某个方法时进入该状态
6、TERMINATED
线程执行结束
Thread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
thread= new Thread(new Runnable() {
@Override
public void run() {
testConsume();
}
});
Log.d(TAG, "onCreate1: state="+thread.getState());
thread.start();
Log.d(TAG, "onCreate2: state="+thread.getState());
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume: state="+thread.getState());
}
此时log打印如下:
2021-03-01 16:20:53.311 12578-12578/com.shan.myapplication D/hahhhxxxx: onCreate1: state=NEW
2021-03-01 16:20:53.312 12578-12578/com.shan.myapplication D/hahhhxxxx: onCreate2: state=RUNNABLE
2021-03-01 16:20:53.331 12578-12578/com.shan.myapplication D/hahhhxxxx: onResume: state=TERMINATED
疑难点
(1)BLOCKED和WAITING的区别是WAITING等待某一条件,BLOCKED等待的是对象锁;
(2)BLOCKED与中断interrupt的区别:BLOCKED是线程的一个状态,interrupt用于线程自身设置一个标志位,在java中需要开发者自己根据这个标志或者InterruptedException然后执行相应的动作。在非死锁的情况下interrupt可以打断BLOCKED状态。
final Object lock1 = new Object();
Thread thread1 = new Thread() {
public void run() {
try {
synchronized (lock1) {
Thread.sleep(10000000);// 不会在这里死掉
System.out.println(Thread.currentThread());
}
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("InterruptedException1 e="+e.getMessage()+",thread1.state="+getState());
}
}
};
System.out.println("Starting thread...");
thread1.start();
Thread.sleep(3000);
System.out.println("Interrupting thread...,thread1="+thread1.getState());
thread1.interrupt(); //中断
Thread.sleep(3000);
System.out.println("Stopping application...thread1="+thread1.getState());
log打印如下
2021-03-01 19:09:44.795 16183-16221/com.shan.myapplication I/System.out: Starting thread...
2021-03-01 19:09:47.797 16183-16221/com.shan.myapplication I/System.out: Interrupting thread...,thread1=TIMED_WAITING
2021-03-01 19:09:47.805 16183-16222/com.shan.myapplication I/System.out: InterruptedException1 e=null,thread1.state=RUNNABLE
2021-03-01 19:09:50.800 16183-16221/com.shan.myapplication I/System.out: Stopping application...thread1=TERMINATED
生产者消费者模型
通过notify和wait可以创建一个生产者消费者模型
仓库类Storage
/**
* 生产者和消费者的问题
* wait、notify/notifyAll() 实现
*/
public class Storage implements AbstractStorage {
//仓库最大容量
private final int MAX_SIZE = 100;
//仓库存储的载体
private LinkedList list = new LinkedList();
//生产产品
public void produce(int num){
//同步
synchronized (list){
//仓库剩余的容量不足以存放即将要生产的数量,暂停生产
while(list.size()+num > MAX_SIZE){
System.out.println("【要生产的产品数量】:" + num + "\t【库存量】:"
+ list.size() + "\t暂时不能执行生产任务!");
try {
//条件不满足,生产阻塞
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<num;i++){
list.add(new Object());
}
System.out.println("【已经生产产品数】:" + num + "\t【现仓储量为】:" + list.size());
list.notifyAll();
}
}
//消费产品
public void consume(int num){
synchronized (list){
//不满足消费条件
while(num > list.size()){
// if(num > list.size()){ if会导致唤醒后list.remove()异常
System.out.println("【要消费的产品数量】:" + num + "\t【库存量】:"
+ list.size() + "\t暂时不能执行消费任务!");
try {
System.out.println("consume0");
list.wait();//如果通过notify或者notifyAll被唤醒,那么程序开始执行wait的下一句代码打印consume1
System.out.println("consume1");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("consume2");
}
System.out.println("开始消费产品");
//消费条件满足,开始消费
for(int i=0;i<num;i++){
list.remove();
}
System.out.println("【已经消费产品数】:" + num + "\t【现仓储量为】:" + list.size());
list.notifyAll();
}
}
生产者类
public class Producer extends Thread{
//每次生产的数量
private int num ;
//所属的仓库
public AbstractStorage abstractStorage;
public Producer(AbstractStorage abstractStorage){
this.abstractStorage = abstractStorage;
}
public void setNum(int num){
this.num = num;
}
// 线程run函数
@Override
public void run()
{
produce(num);
}
// 调用仓库Storage的生产函数
public void produce(int num)
{
abstractStorage.produce(num);
}
}
消费者类
public class Producer extends Thread{
//每次生产的数量
private int num ;
//所属的仓库
public AbstractStorage abstractStorage;
public Producer(AbstractStorage abstractStorage){
this.abstractStorage = abstractStorage;
}
public void setNum(int num){
this.num = num;
}
// 线程run函数
@Override
public void run()
{
produce(num);
}
// 调用仓库Storage的生产函数
public void produce(int num)
{
abstractStorage.produce(num);
}
}
抽象接口
public interface AbstractStorage {
void consume(int num);
void produce(int num);
}
测试程序
private void testConsume() {
// 仓库对象
AbstractStorage abstractStorage = new Storage();
// 生产者对象
Producer p1 = new Producer(abstractStorage);
Producer p2 = new Producer(abstractStorage);
Producer p3 = new Producer(abstractStorage);
Producer p4 = new Producer(abstractStorage);
Producer p5 = new Producer(abstractStorage);
Producer p6 = new Producer(abstractStorage);
Producer p7 = new Producer(abstractStorage);
// 消费者对象
Consumer c1 = new Consumer(abstractStorage);
Consumer c2 = new Consumer(abstractStorage);
Consumer c3 = new Consumer(abstractStorage);
// 设置生产者产品生产数量
p1.setNum(10);
p2.setNum(10);
p3.setNum(10);
p4.setNum(10);
p5.setNum(10);
p6.setNum(10);
p7.setNum(80);
// 设置消费者产品消费数量
c1.setNum(50);
c2.setNum(20);
c3.setNum(30);
// 线程开始执行
c1.start();
c2.start();
c3.start();
p1.start();
p2.start();
p3.start();
p4.start();
p5.start();
p6.start();
p7.start();
}
log打印如下
2021-03-02 09:54:57.505 13063-13110/com.shan.myapplication I/System.out: 【要消费的产品数量】:50 【库存量】:0 暂时不能执行消费任务!
2021-03-02 09:54:57.505 13063-13110/com.shan.myapplication I/System.out: consume0
2021-03-02 09:54:57.506 13063-13115/com.shan.myapplication I/System.out: 【已经生产产品数】:10 【现仓储量为】:10
2021-03-02 09:54:57.507 13063-13117/com.shan.myapplication I/System.out: 【已经生产产品数】:10 【现仓储量为】:20
2021-03-02 09:54:57.507 13063-13113/com.shan.myapplication I/System.out: 【已经生产产品数】:10 【现仓储量为】:30
2021-03-02 09:54:57.508 13063-13112/com.shan.myapplication I/System.out: 开始消费产品
2021-03-02 09:54:57.508 13063-13112/com.shan.myapplication I/System.out: 【已经消费产品数】:30 【现仓储量为】:0
2021-03-02 09:54:57.509 13063-13114/com.shan.myapplication I/System.out: 【已经生产产品数】:10 【现仓储量为】:10
2021-03-02 09:54:57.510 13063-13111/com.shan.myapplication I/System.out: 【要消费的产品数量】:20 【库存量】:10 暂时不能执行消费任务!
2021-03-02 09:54:57.510 13063-13111/com.shan.myapplication I/System.out: consume0
2021-03-02 09:54:57.512 13063-13116/com.shan.myapplication I/System.out: 【已经生产产品数】:10 【现仓储量为】:20
2021-03-02 09:54:57.512 13063-13111/com.shan.myapplication I/System.out: consume1
2021-03-02 09:54:57.512 13063-13111/com.shan.myapplication I/System.out: consume2
2021-03-02 09:54:57.513 13063-13111/com.shan.myapplication I/System.out: 开始消费产品
2021-03-02 09:54:57.513 13063-13111/com.shan.myapplication I/System.out: 【已经消费产品数】:20 【现仓储量为】:0
2021-03-02 09:54:57.514 13063-13110/com.shan.myapplication I/System.out: consume1
2021-03-02 09:54:57.514 13063-13110/com.shan.myapplication I/System.out: consume2
2021-03-02 09:54:57.514 13063-13110/com.shan.myapplication I/System.out: 【要消费的产品数量】:50 【库存量】:0 暂时不能执行消费任务!
2021-03-02 09:54:57.515 13063-13110/com.shan.myapplication I/System.out: consume0
2021-03-02 09:54:57.515 13063-13119/com.shan.myapplication I/System.out: 【已经生产产品数】:80 【现仓储量为】:80
2021-03-02 09:54:57.516 13063-13110/com.shan.myapplication I/System.out: consume1
2021-03-02 09:54:57.516 13063-13110/com.shan.myapplication I/System.out: consume2
2021-03-02 09:54:57.517 13063-13110/com.shan.myapplication I/System.out: 开始消费产品
2021-03-02 09:54:57.517 13063-13110/com.shan.myapplication I/System.out: 【已经消费产品数】:50 【现仓储量为】:30
2021-03-02 09:54:57.518 13063-13118/com.shan.myapplication I/System.out: 【已经生产产品数】:10 【现仓储量为】:40
参考资料