本篇是线程基础知识系列的第二篇,主要说下线程管理相关知识点。
线程基础知识系列(一)线程的创建和启动:说明了线程的2种创建和启动,join(),daemon线程,Callable
任务。
本文的主要内容
线程的状态
线程的优先级
sleep vs wait
线程的流程控制
Interrupt
yield让出你的CPU
1.线程的状态
以《线程基础知识系列(一)线程的创建和启动》这张图,是程序的运行时线程信息截图。有main线程,user Threads,daemon Threads。现在咱们把重点放在线程状态上(RUNNING,WAIT,SLEEPING...)
线程的状态有哪些?状态转换图是怎么样的?
线程状态转换图
状态信息是枚举类型,线程状态分别是:New,RUNNABLE,BLOCKED,WAITING,TIMED_WAITED,TERMINATED.
1.1 TimedWaitThreadDemo.java ,主要演示了TIMED_WAITING状态的触发时机
package com.threadexample.mgr;
import java.util.concurrent.TimeUnit;
/**
* Created by Administrator on 2016/6/26.
*/
public class TimedWaitThreadDemo {
public static void main(String[] args) throws InterruptedException {
Thread mythread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("begin sleep start");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end sleep start");
}
});
mythread.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("mythread.state:"+mythread.getState());
}
}
执行结果
-----------------------
begin sleep start
mythread.state:TIMED_WAITING
end sleep start
--------------------------
1.2 WaitThreadDemo.java ,主要演示了WAITING状态的触发时机
package com.threadexample.mgr;
import java.util.concurrent.TimeUnit;
/**
* Created by Administrator on 2016/6/26.
*/
public class WaitThreadDemo {
private final static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread mythread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
mythread.start();
TimeUnit.SECONDS.sleep(1);//休眠1秒,保证能进入同步块
System.out.println("mythread.state:"+mythread.getState());
}
}
执行结果
----------------
mythread.state:WAITING
----------------
1.3BlockedThreadDemo.java,主要演示了BLOCKED状态的触发时机。需要涉及多个线程资源争用,所以需要多个线程。
package com.threadexample.mgr;
import java.util.concurrent.TimeUnit;
/**
* Created by Administrator on 2016/6/26.
*/
public class BlockedThreadDemo {
private final static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Runnable ruunnble = new Runnable() {
@Override
public void run() {
synchronized (lock){
System.out.println(Thread.currentThread().getName()+"开始业务操作");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"完成业务操作");
}
}
};
Thread mythread = new Thread(ruunnble);
Thread mythread2 = new Thread(ruunnble);
mythread.start();
mythread2.start();
System.out.println("mythread.state:" + mythread.getState());
System.out.println("mythread2.state:"+mythread2.getState());
}
}
执行结果
-------------------------
Thread-0开始业务操作
mythread.state:RUNNABLE
mythread2.state:BLOCKED
Thread-0完成业务操作
Thread-1开始业务操作
Thread-1完成业务操作
-------------------------
2.线程的优先级
线程有个优先级属性,优先级是从1到10的整数类型。
Thread Priority Constants | Integer Value |
---|---|
MIN_PRIORITY | 1 |
NORM_PRIORITY | 5 |
MAX_PRIORITY | 10 |
理论上来说,优先级越高,获取CPU的的时间越大,这仅仅是概率问题,并不能保证优先级越高的线程一定先执行。线程的优先级,对于调度器而言,仅仅相当于一个提示器的作用,具体如何执行,还要看CPU的心情。
需要说明的事,依靠优先级的顺序来决定线程的执行顺序,是不靠谱的。线程的优先级是依靠操作系统底层调度的,由于操作系统的调度方式也存在差异,所以线程优先级的执行行为也会存在差异。
JAVA 提供了setPriority() 和getPriority()管理线程。
PriorityThreadDemo.java 演示了线程优先级的管理,通过分析结果也验证了,优先级并不能保证线程的执行顺序。
package com.threadexample.mgr;
import java.util.ArrayList;
import java.util.List;
public class PriorityThreadDemo {
public static void main(String[] args) {
Runnable ruunnble = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"\t优先级:"+Thread.currentThread().getPriority()+"\t执行完成");
}
};
List<Thread> tasks = new ArrayList<Thread>();
for(int i=Thread.MIN_PRIORITY;i<=Thread.MAX_PRIORITY;i++){
Thread thread = new Thread(ruunnble);
thread.setPriority(i);
tasks.add(thread);
}
for(Thread thread:tasks){
thread.start();
}
}
}
执行结果
--------------------
Thread-0 优先级:1 执行完成
Thread-4 优先级:5 执行完成
Thread-2 优先级:3 执行完成
Thread-1 优先级:2 执行完成
Thread-3 优先级:4 执行完成
Thread-5 优先级:6 执行完成
Thread-6 优先级:7 执行完成
Thread-8 优先级:9 执行完成
Thread-9 优先级:10 执行完成
Thread-7 优先级:8 执行完成
--------------------
3.sleep vs wait
sleep()和wait()方法,对线程的影响“当前线程停止执行”。但他们之间的存在本质区别
区别 | wait | sleep |
Class belongs | 属于java.lang.Object class | 属于java.lang.Thread class |
Context (上下文) | 只能在Synchronized context 中调用。也就是常见的synchronized快中。 | 任意上下文 |
Locking (锁管理) | 释放锁 | 不释放锁 |
Wake up condition 唤醒条件 | 被另外线程,通过调用notify() or notifyAll() 唤醒 | interrupt 和时间过期机制 |
Execution (执行时机) | 线程间的通信 | 属于Thread的静态方法 |
4.线程的流程控制
SN
Methods with Description | |
---|---|
1 暂停 | public void suspend() This method puts a thread in suspended state and can be resumed using resume() method. |
2 停止 | public void stop() This method stops a thread completely. |
3 恢复 | public void resume() This method resumes a thread which was suspended using suspend() method. |
4 等待 | public void wait() Causes the current thread to wait until another thread invokes the notify(). |
5 唤醒 | public void notify() Wakes up a single thread that is waiting on this object's monitor. |
遗憾的是suspend( ), resume( ), and stop( ) 这些方法都被弃用了,不建议使用。
ThreadControlDemo.java提供了暂停,恢复,停止的功能。有一点说明,必须保证状态信息的同步。
package com.threadexample.mgr;
class RunnableDemo implements Runnable {
public Thread t;
private String threadName;
boolean suspended = false;
RunnableDemo(String name) {
threadName = name;
System.out.println("Creating " + threadName);
}
public void run() {
System.out.println("Running " + threadName);
try {
for (int i = 10; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// Let the thread sleep for a while.
Thread.sleep(300);
synchronized (this) {
while (suspended) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start() {
System.out.println("Starting " + threadName);
if (t == null) {
t = new Thread(this, threadName);
t.start();
}
}
void suspend() {
suspended = true;
}
synchronized void resume() {
suspended = false;
notify();
}
}
public class ThreadControlDemo {
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo("Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo("Thread-2");
R2.start();
try {
Thread.sleep(1000);
R1.suspend();
System.out.println("Suspending First Thread");
Thread.sleep(1000);
R1.resume();
System.out.println("Resuming First Thread");
R2.suspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
R2.resume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
try {
System.out.println("Waiting for threads to finish.");
R1.t.join();
R2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
5.Interrupt
interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
InterruptDemo.java展示了Thread.interrupted()的使用。
package com.threadexample.mgr;
public class InterruptDemo {
public static void main(String[] args) {
System.out.println("#1:" + Thread.interrupted());
// Now interrupt the main thread
Thread.currentThread().interrupt();
// Check if it has been interrupted
System.out.println("#2:" + Thread.interrupted());
// Check again if it has been interrupted
System.out.println("#3:" + Thread.interrupted());
}
}
执行结果
----------------------
#1:false
#2:true
#3:false
----------------------
分析结果得知,Thread.interrupted()会清理中断标记。
InterruptDemo2.java展示了isInterrupted()的使用。第一次调用和第二次调用返回结果一样。
package com.threadexample.mgr;
public class InterruptDemo2 {
public static void main(String[] args) {
Thread th1 = new Thread(new Runnable() {
@Override
public void run() {
Thread currentThread = Thread.currentThread();
currentThread.interrupt();
System.out.println("isInterrupted()#1="+currentThread.isInterrupted());
System.out.println("isInterrupted()#2="+currentThread.isInterrupted());
}
});
th1.start();
}
}
执行结果
----------------------
isInterrupted()#1=true
isInterrupted()#2=true
---------------------
isInterrupted() VS interrupted()
方面 | isInterrupted() | interrupted() |
不同点 | Thread 静态方法。返回结果决定于当前线程的是否被中断。 该方法会清理线程的中断状态 | Thread的实例方法。不会被清理。 |
相似点 | public static boolean interrupted () { 调用同一个方法,参数不同而已 private native boolean isInterrupted( boolean ClearInterrupted); | public boolean isInterrupted () { return isInterrupted( false); } |
6.yield ()放弃你的CPU
yield(),是一个影响调度器的hint,作用是临时放弃CPU资源,允许其他线程执行。
YieldDemo.java,展示了yield()的使用
package com.threadexample.mgr;
/**
* Created by Administrator on 2016/6/26.
*/
public class YieldDemo implements Runnable {
Thread t;
YieldDemo(String str) {
t = new Thread(this, str);
// this will call run() function
t.start();
}
public void run() {
for (int i = 0; i < 5; i++) {
// yields control to another thread every 5 iterations
if ((i % 5) == 0) {
System.out.println(Thread.currentThread().getName() + " yielding control...");
/* causes the currently executing thread object to temporarily
pause and allow other threads to execute */
Thread.yield();
}
}
System.out.println(Thread.currentThread().getName() + " has finished executing.");
}
public static void main(String[] args) {
new YieldDemo("Thread 1");
new YieldDemo("Thread 2");
new YieldDemo("Thread 3");
}
}
结果
----------
Thread 1 yielding control...
Thread 3 yielding control...
Thread 2 yielding control...
Thread 3 has finished executing.
Thread 1 has finished executing.
Thread 2 has finished executing.
---------
但是执行了几次,结果一直在变化。yield根本不能保证执行顺序。
其他
Thread.setName()
Thread.isAlive()
ThreadGroup
Thread.activeCount()
资源
http://javahungry.blogspot.com/2015/11/5-difference-between-sleep-and-wait-with-example.html
http://www.tutorialspoint.com/java/java_thread_control.htm
http://www.java2s.com/Tutorials/Java/Java_Thread/0100__Java_Thread_Interrupt.htm
转载于:https://blog.51cto.com/dba10g/1793099