本篇是线程基础知识系列的第二篇,主要简单江夏线程管理相关知识点。
线程基础知识系列(一)线程的创建和启动:说明了线程的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
本文出自 “简单” 博客,请务必保留此出处http://dba10g.blog.51cto.com/764602/1793099
原文地址:http://dba10g.blog.51cto.com/764602/1793099