sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
例子
SleepThread.java
package cn.zdfy.thread.funsThread;
public class SleepThread implements Runnable {
private String name;
private int mIndex = 0;
private int count;
public int getmIndex() {
return mIndex;
}
public void setmIndex(int mIndex) {
this.mIndex = mIndex;
}
public SleepThread(String name, int count) {
this.name = name;
this.count = count;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " ====线程运行开始!");
for (int i = 0; i < count; i++) {
mIndex = i;
System.out.println("子线程" + name + "运行 : " + i);
}
System.out.println(Thread.currentThread().getName() + " ====线程运行结束!");
}
}
测试代码
package cn.zdfy.thread.funsThread;
public class SleepThreadTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + " 线程 ==== 执行 start");
SleepThread sa = new SleepThread("A", 10);
Thread ta = new Thread(sa);
try {
System.out.println(Thread.currentThread().getName() + " 线程 睡眠 1s 前");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 线程 睡眠 1s 后");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 线程 ==== 执行 end");
}
}
效果
main 线程 ==== 执行 start
main 线程 睡眠 1s 前
main 线程 睡眠 1s 后
main 线程 ==== 执行 end
join()
join是Thread类的一个方法,启动线程后直接调用,即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
例子
JoinThread.java
package cn.zdfy.thread.funsThread;
/**
* @author zhangpeng
*
*/
public class JoinThread implements Runnable {
private String name;
private int mIndex =0;
private int count;
public int getmIndex() {
return mIndex;
}
public void setmIndex(int mIndex) {
this.mIndex = mIndex;
}
public JoinThread(String name, int count) {
super();
this.name = name;
this.count = count;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "====线程运行开始!");
for (int i = 0; i < count; i++) {
mIndex=i;
System.out.println("子线程" + name + "运行 : " + i);
try {
Thread.sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "====线程运行结束!");
}
}
测试代码
package cn.zdfy.thread.funsThread;
public class JoinThreadTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + "主线程运行开始!");
JoinThread thread1 = new JoinThread("A", 10);
JoinThread thread2 = new JoinThread("B", 10);
Thread tA = new Thread(thread1);
Thread tB = new Thread(thread2);
tA.start();
tB.start();
try {
tA.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
tB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "主线程运行结束!");
}
}
加了join
main主线程运行开始!
Thread-1====线程运行开始!
Thread-0====线程运行开始!
子线程A运行 : 0
子线程B运行 : 0
子线程B运行 : 1
子线程A运行 : 1
子线程B运行 : 2
子线程A运行 : 2
子线程B运行 : 3
子线程A运行 : 3
子线程B运行 : 4
子线程A运行 : 4
子线程B运行 : 5
子线程A运行 : 5
子线程B运行 : 6
子线程A运行 : 6
子线程B运行 : 7
子线程A运行 : 7
子线程B运行 : 8
子线程A运行 : 8
子线程B运行 : 9
子线程A运行 : 9
Thread-1====线程运行结束!
Thread-0====线程运行结束!
main主线程运行结束!
不加join (注释掉代码)
main主线程运行开始!
main主线程运行结束!
Thread-0====线程运行开始!
Thread-1====线程运行开始!
子线程A运行 : 0
子线程B运行 : 0
子线程A运行 : 1
子线程B运行 : 1
子线程A运行 : 2
子线程B运行 : 2
子线程B运行 : 3
子线程A运行 : 3
子线程A运行 : 4
子线程B运行 : 4
子线程A运行 : 5
子线程B运行 : 5
子线程A运行 : 6
子线程B运行 : 6
子线程A运行 : 7
子线程B运行 : 7
子线程B运行 : 8
子线程A运行 : 8
子线程B运行 : 9
子线程A运行 : 9
Thread-1====线程运行结束!
Thread-0====线程运行结束!
总结
加了join会主线程等待该线程结束
yield()
Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。
yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
例子
YieldThread.java
package cn.zdfy.thread.funsThread;
public class YieldThread extends Thread {
public YieldThread(String name) {
super(name);
}
@Override
public void run() {
super.run();
for (int i = 1; i <= 50; i++) {
System.out.println("" + this.getName() + "=======" + i);
if (i == 10 || i==20 || i==30) {
System.out.println(this.getName() + "线程开始退让 ================ 让 cpu 重新分配机会");
this.yield();
}
}
}
}
测试代码
package cn.zdfy.thread.funsThread;
public class YieldThreadTest {
public static void main(String[] args) {
YieldThread ya = new YieldThread("A");
YieldThread yb = new YieldThread("B");
ya.start();
yb.start();
}
}
效果
A=======1
B=======1
A=======2
B=======2
B=======3
B=======4
A=======3
B=======5
A=======4
B=======6
B=======7
B=======8
B=======9
B=======10
B线程开始退让 ================ 让 cpu 重新分配机会
A=======5
A=======6
A=======7
A=======8
A=======9
A=======10
A线程开始退让 ================ 让 cpu 重新分配机会
B=======11
A=======11
A=======12
A=======13
A=======14
A=======15
A=======16
A=======17
A=======18
A=======19
A=======20
A线程开始退让 ================ 让 cpu 重新分配机会
B=======12
B=======13
B=======14
B=======15
B=======16
B=======17
A=======21
B=======18
A=======22
B=======19
B=======20
B线程开始退让 ================ 让 cpu 重新分配机会
A=======23
A=======24
A=======25
A=======26
B=======21
A=======27
B=======22
A=======28
A=======29
A=======30
A线程开始退让 ================ 让 cpu 重新分配机会
B=======23
B=======24
B=======25
B=======26
B=======27
B=======28
B=======29
B=======30
B线程开始退让 ================ 让 cpu 重新分配机会
A=======31
A=======32
A=======33
A=======34
A=======35
A=======36
A=======37
A=======38
A=======39
A=======40
A=======41
A=======42
A=======43
A=======44
A=======45
A=======46
A=======47
A=======48
A=======49
A=======50
B=======31
B=======32
B=======33
B=======34
B=======35
B=======36
B=======37
B=======38
B=======39
B=======40
B=======41
B=======42
B=======43
B=======44
B=======45
B=======46
B=======47
B=======48
B=======49
B=======50
结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果,说白了只是重新回到CPU重新分配的时机
setPriority():
更改线程的优先级。
MIN_PRIORITY = 1
NORM_PRIORITY = 5
MAX_PRIORITY = 10
例子
PriorityThread .java
package cn.zdfy.thread.funsThread;
public class PriorityThread extends Thread {
public PriorityThread(String name) {
super(name);
}
@Override
public void run() {
super.run();
for (int i = 1; i <= 10; i++) {
System.out.println(this.getName() + "=======" + i);
}
}
}
测试代码
package cn.zdfy.thread.funsThread;
public class PriorityThreadTest {
public static void main(String[] args) {
PriorityThread pa = new PriorityThread("A");
PriorityThread pb = new PriorityThread("B");
pa.setPriority(Thread.MAX_PRIORITY);
pb.setPriority(Thread.MIN_PRIORITY);
pa.start();
pb.start();
}
}
效果
A=======1
A=======2
A=======3
A=======4
A=======5
A=======6
A=======7
A=======8
A=======9
A=======10
B=======1
B=======2
B=======3
B=======4
B=======5
B=======6
B=======7
B=======8
B=======9
B=======10
总结: 优先级高的优先执行
wait()
Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){…}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
单单在概念上理解清楚了还不够,需要在实际的例子中进行测试才能更好的理解。对Object.wait(),Object.notify()的应用最经典的例子,应该是三线程打印ABC的问题了吧,这是一道比较经典的面试题,题目要求如下:
建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。
例子
WaitThread.java
package cn.zdfy.thread.funsThread;
public class WaitThread implements Runnable {
private String name;
private Object prevObj;
private Object selfObj;
public WaitThread(String name, Object prevObj, Object selfObj) {
this.name = name;
this.prevObj = prevObj;
this.selfObj = selfObj;
}
@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (prevObj) {
synchronized (selfObj) {
System.out.print(name);
count--;
selfObj.notify(); // 唤醒
}
try {
prevObj.wait(); // 释放对象锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
测试代码
WaitThreadTest.java
package cn.zdfy.thread.funsThread;
public class WaitThreadTest {
public static void main(String[] args) throws InterruptedException {
Object a = new Object();
Object b = new Object();
Object c = new Object();
WaitThread wa = new WaitThread("A", c, a);
WaitThread wb = new WaitThread("B", a, b);
WaitThread wc = new WaitThread("C", b, c);
new Thread(wa).start();
Thread.sleep(100); // 确保按顺序A、B、C执行
new Thread(wb).start();
Thread.sleep(100);
new Thread(wc).start();
Thread.sleep(100);
}
}
效果
ABCABCABCABCABCABCABCABCABCABC