说明了线程的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状态的触发时机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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状态的触发时机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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状态的触发时机。需要涉及多个线程资源争用,所以需要多个线程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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 演示了线程优先级的管理,通过分析结果也验证了,优先级并不能保证线程的执行顺序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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提供了暂停,恢复,停止的功能。有一点说明,必须保证状态信息的同步。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
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()的使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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()的使用。第一次调用和第二次调用返回结果一样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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()的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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()
本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1793099,如需转载请自行联系原作者