Java多线程常用方法,过期方法
线程休眠 sleep
- sleep(long)指定当前线程阻塞的毫秒数
- sleep存在异常InterruptException
- sleep时间达到后线程进入就绪状态
- sleep可以模拟网络延时
每个对象都有一把锁,sleep不会释放锁
线程礼让 yield
yield() 暂停当前线程,使当前线程从running状态变为Ready状态,
让cpu重新调度。至于cpu选中那个线程执行是随机的,完全取决于cpu调度。
public class ThreadYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"A").start();
new Thread(myYield,"B").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " start...");
Thread.yield();
System.out.println(Thread.currentThread().getName() + " stop...");
}
}
执行结果
多执行几次,会发现不一样的结果
A start...
B start...
A stop...
B stop...
Thread.join()的使用
一个线程A执行了B.join()时,当前线程A等待B线程终止之后才执行线程A剩下部分。
join()保证线程B的可见性,即线程B中修改的变量,线程A可见。
/**
* Thread join方法
*/
public class Join {
public static void main(String[] args) throws Exception {
Thread previous = Thread.currentThread();
for (int i = 0; i < 10; i++) {
// 每个线程拥有前一个线程的引用,需要等待前一个线程终止,才能从等待中返回
Thread thread = new Thread(new Domino(previous), String.valueOf(i));
thread.start();
previous = thread;
}
TimeUnit.SECONDS.sleep(5);
System.out.println(Thread.currentThread().getName() + " terminate.");
}
static class Domino implements Runnable {
private Thread thread;
public Domino(Thread thread) {
this.thread = thread;
}
public void run() {
try {
thread.join();
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + " terminate.");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
main terminate.
0 terminate.
1 terminate.
2 terminate.
3 terminate.
4 terminate.
5 terminate.
6 terminate.
7 terminate.
8 terminate.
9 terminate.
Process finished with exit code 0
每个线程终止的前提是前驱线程的终止,每个线程等待前驱线程 终止后,才从join()方法返回。
join方法相当于插队执行,最早插队的是main,依次为0-9,故执行顺序如上。
a.join()方法,等待a线程执行完毕,再执行其他线程,其他线程阻塞
public class ThreadJoin {
public static void main(String[] args) throws InterruptedException {
MyJoin myJoin = new MyJoin();
Thread t1 = new Thread(myJoin, "张三");
t1.start();
for (int i = 0; i < 200; i++) {
Thread.sleep(50);
System.out.println("王五 执行到 " + i);
if (i==100){
t1.join();
}
}
}
}
class MyJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 执行到 " + i);
}
}
}
线程过期的suspend()、resume()和stop()
暂停 suspend()
恢复 resume()
停止 stop()
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* 过期的方法
* 暂停 suspend()
* 恢复 resume()
* 恢复 stop()
* 像音乐播放器的按键一样
*/
public class Deprecated {
public static void main(String[] args) throws Exception {
DateFormat format = new SimpleDateFormat("HH:mm:ss");
Thread printThread = new Thread(new Runner(), "PrintThread");
printThread.setDaemon(true);
printThread.start();
TimeUnit.SECONDS.sleep(3);
// 将PrintThread进行暂停,输出内容工作停止
printThread.suspend();
System.out.println("main suspend PrintThread at " + format.format(new Date()));
TimeUnit.SECONDS.sleep(3);
// 将PrintThread进行恢复,输出内容继续
printThread.resume();
System.out.println("main resume PrintThread at " + format.format(new Date()));
TimeUnit.SECONDS.sleep(3);
// 将PrintThread进行终止,输出内容停止
printThread.stop();
System.out.println("main stop PrintThread at " + format.format(new Date()));
TimeUnit.SECONDS.sleep(3);
}
static class Runner implements Runnable {
@Override
public void run() {
DateFormat format = new SimpleDateFormat("HH:mm:ss");
while (true) {
System.out.println(Thread.currentThread().getName() + " Run at " +
format.format(new Date()));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//执行结果
PrintThread Run at 21:30:27
PrintThread Run at 21:30:28
PrintThread Run at 21:30:29
main suspend PrintThread at 21:30:30
PrintThread Run at 21:30:33
main resume PrintThread at 21:30:33
PrintThread Run at 21:30:34
PrintThread Run at 21:30:35
main stop PrintThread at 21:30:36
Process finished with exit code 0
不建议使用的原因主要有:以suspend()方法为例,在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题。同样,stop()方法在终结 一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。