文章目录
1、常用方法简览
修饰符和类型 | 方法 | 描述 |
---|---|---|
public long | getId() | 返回此线程的标识符 |
public final String | getName() | 返回此线程的名称 |
public final synchronized void | setName(String name) | 将此线程的名称更改为 name |
public Thread.State | getState() | 返回此线程的状态 |
public final void | setPriority(int newPriority) | 更改此线程的优先级 |
public final int | getPriority() | 返回此线程的优先级 |
public static native void | sleep(long millis) | 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行,但是其所拥有的监视器资源,比如锁还是持有不让出的),具体取决于系统定时器和调度程序的精度和准确性 |
public final synchronized void | join() | 等待这个线程死亡(就是霸道插队直到运行结束) |
public static native void | yield() | 对调度程序的一个暗示,即当前线程愿意让出当前使用的处理器 |
public void | interrupt() | 中断这个线程(你需要自行完成中断) |
public final native boolean | isAlive() | 测试这个线程是否活着 |
2、线程等待与通知
在Object类中有一些函数可以用于线程的等待与通知。
Object的线程等待方法如下:
- wait():当一个线程A调用一个共享变量的
wait()
方法时, 线程A会被阻塞挂起,发生下面几种情况才会返回 :- 线程A调用了共享对象
notify()
或者notifyAll()
方法 - 其他线程调用了线程A的
interrupt()
方法,线程A抛出
- 线程A调用了共享对象
- wait(long timeout):这个方法相比 wait() 方法多了一个超时参数,它的不同之处在于,如果线程A调用共享对象的
wait(long timeout)
方法后,没有在指定的 timeout ms时间内被其它线程唤醒,那么这个方法还是会因为超时而返回。 - wait(long timeout, int nanos):其内部调用的是
wait(long timout)
函数,nanos 是附加时间(ns)。
Object唤醒线程主要是下面两个方法:
- notify():一个线程A调用共享对象的
notify()
方法后,会唤醒一个在这个共享变量上调用 wait 系列方法后被挂起的线程。 一个共享变量上可能会有多个线程在等待,具体唤醒哪个等待的线程是随机的。 - notifyAll():不同于在共享变量上调用
notify()
函数会唤醒被阻塞到该共享变量上的一个线程,notifyAll()
方法则会唤醒所有在该共享变量上由于调用 wait 系列方法而被挂起的线程。
Thread类也提供了一个用于等待的方法:
- join():如果一个线程A执行了
thread.join()
语句,其含义是:当前线程A等待 thread线程 终止之后从thread.join()
返回。
来看一下
join()
官方的解释:Waits for this thread to die
就问你霸不霸道?!!!
1、CODE
package mii.thread.demo10;
/**
* 测试插队:join
*/
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程VIP来了" + i);
}
}
public static void main(String[] args) throws InterruptedException {
TestJoin tj = new TestJoin();
// 启动我们的线程
Thread thread = new Thread(tj);
thread.start();
// 主线程
for (int i = 0; i < 10; i++) {
if(i == 5){
thread.join(); // 插队
}
System.out.println("main--" + i);
}
}
}
2、Result
3、线程休眠 sleep
Thread类中的静态方法,当一个执行中的线程A调用了Thread的sleep方法后,线程A会暂时让出指定时间的执行权,但是线程A所拥有的监视器资源,比如锁还是持有不让出的。指定的睡眠时间到了后该函数会正常返回,接着参与 CPU 的调度,获取到 CPU 资源后就可以继续运行。
- sleep(毫秒) 指定当前线程阻塞的毫秒数
- sleep 存在异常 InterruptedException 需要捕获或抛出
- sleep 时间结束后线程进入就绪状态,继续参与 CPU 调度的竞争
- 每个对象都有一个锁,sleep 不会释放锁
1、CODE
package mii.thread.demo10;
/**
* 模拟倒计时
*/
public class TestSleep02 {
public static void main(String[] args) throws InterruptedException {
int i = 10;
while(i >= 0){
System.out.println(i--);
Thread.sleep(1000);
}
}
}
2、Result
3、线程中断
- 建议线程正常停止(利用次数,不建议死循环)
- 建议使用标志位(设置一个标志位flag)
- 不要使用
stop
或destory
等过时或JDK不建议使用的方法
- void interrupt():中断线程,例如,当线程A运行时,线程B可以调用线程
interrupt()
方法来设置线程的中断标志为true 并立即返回。设置标志仅仅是设置标志, 线程A实际并没有被中断, 会继续往下执行。 - boolean isInterrupted():检测当前线程是否被中断。
- boolean interrupted():检测当前线程是否被中断,与
isInterrupted()
不同的是,该方法如果发现当前线程被中断,则会清除中断标志。
1、CODE
package mii.thread.demo10;
/**
* 测试停止:stop
* 1、建议线程正常停止(利用次数,不建议死循环)
* 2、建议使用标志位(设置一个标志位flag)
* 3、不要使用stop或destory等过时或JDK不建议使用的方法
*/
public class TestStop implements Runnable{
// 1、设置一个标志位
private boolean flag = true;
@Override
public void run() {
int i = 0;
while(flag){
System.out.println("run...Thread-->" + i++);
}
}
// 2、设置一个公开方法停止线程,转换标志位
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
TestStop ts = new TestStop();
new Thread(ts).start();
for (int i = 0; i < 20; i++) {
System.out.println("main...time-->" + i);
if(i == 9){
// 调用自己写的stop方法切换标志位,停止线程
ts.stop();
System.out.println("线程该停止了!");
}
}
}
}
2、Result
4、让出优先权 yield
Thread类中的静态方法,当一个线程调用 yield 方法时,实际就是在暗示线程调度器当前线程请求让出自己的CPU ,但是线程调度器可以无条件忽略这个暗示。
- 线程礼让,让当前正在执行的线程暂停,但不阻塞
- 线程从运行状态转为就绪状态
- 让 CPU 重新调度,礼让不一定成功,全看 CPU 心情
1、CODE
package mii.thread.demo10;
/**
* 测试礼让:yield
* 礼让不一定成功,看CPU心情
*/
public class TestYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程开始执行");
Thread.yield(); // 礼让
System.out.println(Thread.currentThread().getName() + "线程停止执行");
}
public static void main(String[] args) {
TestYield ty = new TestYield();
new Thread(ty, "A").start();
new Thread(ty, "B").start();
}
}
2、Result
5、线程优先级 Priority
Java 提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行(优先级高低只影响被调用的概率,不是说优先级高就先执行,依然会出现性能倒置的情况,完全看 CPU 心情)
线程的优先级用数字表示,范围从1~10
/** 线程可以具有的最小优先级. */ public final static int MIN_PRIORITY = 1; /* 分配给线程的默认优先级. */ public final static int NORM_PRIORITY = 5; /* 线程可以具有的最大优先级. */ public final static int MAX_PRIORITY = 10;
使用以下方式改变或获取优先级
/* 修改此线程的优先级. */ public final void setPriority(int newPriority) { ThreadGroup g; checkAccess(); if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if((g = getThreadGroup()) != null) { if (newPriority > g.getMaxPriority()) { newPriority = g.getMaxPriority(); } setPriority0(priority = newPriority); } } /* 返回此线程的优先级. */ public final int getPriority() { return priority; }
1、CODE
package mii.thread.demo11线程优先级;
/**
* 测试线程优先级:priority
*/
public class TestPriority {
public static void main(String[] args) {
// 打印主线程优先级
System.out.println(Thread.currentThread().getName() + "--->" +
Thread.currentThread().getPriority());
Thread thread0 = new Thread(()->
System.out.println(Thread.currentThread().getName() + "--->" +
Thread.currentThread().getPriority()));
Thread thread1 = new Thread(()->
System.out.println(Thread.currentThread().getName() + "--->" +
Thread.currentThread().getPriority()));
Thread thread2 = new Thread(()->
System.out.println(Thread.currentThread().getName() + "--->" +
Thread.currentThread().getPriority()));
Thread thread3 = new Thread(()->
System.out.println(Thread.currentThread().getName() + "--->" +
Thread.currentThread().getPriority()));
// 先设置优先级再启动
thread1.setPriority(1);
thread2.setPriority(4);
thread3.setPriority(Thread.MAX_PRIORITY);
thread0.start();
thread1.start();
thread2.start();
thread3.start();
}
}