您的位置:首页 > 编程语言 > Java开发

Java 线程的基本状态和操作

2017-01-01 21:22 375 查看

线程的几种状态

在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。

第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。

第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,

但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。

第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。

sleep,suspend,wait等方法都可以导致线程阻塞。

第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。

对于已经死亡的线程,无法再使用start方法令其进入就绪。

操作线程的基本函数

wait()

当一个线程执行到wait()时, 他会进入到一个和该对象相关的等待池中,同时失去了对象的锁机制,使得其他线程可以访问.

用户可以使用notify或notifyAll来唤醒当前等待池中的线程

Note:wait()和notify(),notifyAll()必须放在Synchronized Block中,否则会抛出异常

notify()会随机唤醒一个,一般使用notifyAll()就可以

/**
* Created by yangtianrui on 17-1-1.
* 线程的wait, sleep, join, yield方法
*/
public class WaitAndNotifyDemo {

// 用于等待唤醒的对象
private final static Object sLockObject = new Object();

public static void main(String[] args) {
waitAndNotifyAll();
}

private static void waitAndNotifyAll() {
System.out.println("主线程执行");
Thread thread = new WaitThread();
thread.start();
long startTime = System.currentTimeMillis();
try {
synchronized (sLockObject) {
System.out.println("主线程等待");
sLockObject.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
long deltaTime = System.currentTimeMillis();
System.out.println("主线程等待了 " + (deltaTime - startTime));
}

private static class WaitThread extends Thread {
@Override
public void run() {
try {
synchronized (sLockObject) {
Thread.sleep(3000);
// 释放当前锁
// 或者使用notifyAll();
sLockObject.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

/*
主线程执行
主线程等待
主线程等待了 3000
*/


sleep()

该函数是sleep的静态函数,作用是使调用线程进入睡眠状态,因此他不能改变对象的锁机制,所以当一个Synchronized块中调用sleep(),

并不会使使当前线程释放掉这个锁,即使睡眠也持有这个对象锁

join()

等待目标线程执行完成后再继续执行

/**
* Created by yangtianrui on 17-1-1.
* Join() 阻塞当前调用Join()函数所在的线程,直到接收线程执行完毕后在执行
*/
public class JoinDemo {

public static void main(String[] args) {
Thread thread1 = new WorkerThread("worker-1");
Thread thread2 = new WorkerThread("worker-2");
thread1.start();
System.out.println("启动线程1");
try {
// worker1 的join函数后,主线程会一直阻塞到thread1执行完毕
thread1.join();
System.out.println("启动线程2");
thread2.start();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("主线程继续执行");
}

private static class WorkerThread extends Thread {
public WorkerThread(String name) {
super(name);
}

@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work in  " + getName());
}
}
}

/*
启动线程1
work in  worker-1
启动线程2
work in  worker-2
主线程继续执行
*/


yield()

线程礼让,目标线程由运行状态转换成就绪状态,也就是让出执行权限,让其他线程得以优先执行,但其他线程能否优先执行是未知的.

Note: 让出执行时间并不是让出持有的对象锁

/**
* Created by yangtianrui on 17-1-1.
* yield()使该函数所在的线程让出执行时间给其他已经就绪的线程
* <p>
* 让出执行时间并不是让出持有的对象锁
*/

public class YieldDemo {

public static void main(String[] args) {
Thread thread1 = new YieldThread("thread-1");
Thread thread2 = new YieldThread("thread-2");

thread1.start();
thread2.start();
}

private static class YieldThread extends Thread {
public YieldThread(String name) {
super(name);
}

@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(getName() + " priority=" + getPriority() + " i=" + i);
// 每两次,执行一次yield()
if (i % 2 == 0) {
Thread.yield();
}
}
}
}
}
/*
到偶数时,会切换一次线程
thread-1 priority=5 i=0
thread-2 priority=5 i=0
thread-1 priority=5 i=1
thread-1 priority=5 i=2
thread-2 priority=5 i=1
thread-1 priority=5 i=3
thread-2 priority=5 i=2
thread-1 priority=5 i=4
thread-2 priority=5 i=3
thread-2 priority=5 i=4
thread-1 priority=5 i=5
thread-1 priority=5 i=6
thread-2 priority=5 i=5
thread-2 priority=5 i=6
thread-1 priority=5 i=7
*/


Note: yield()调用之后,其他线程并不一定会抢占到 执行时间
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: