23.5线程的常用方法
23.5.1线程的名称
thread.setName();//设置线程名
thread.getName();//返回系统分配的线程名字
23.5.2线程的睡眠(应用广泛)
Thread.sleep(long millis);让线程“至少”休眠millis毫秒
当前线程睡眠/millis的时间(millis指定睡眠时间是其最小的不执行时间,因为sleep(millis)休眠到达后,无法保证会被JVM立即调度); 作用:保持对象锁,让出CPU,调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留一定的时间给其他线程执行的机会;
//笔记
public class MyRunnable {
public static void main(String[] args) {
String content = "程序正在加载中...";
//try..catch..写在循环外面提高性能。
try {
for (int i = 0; i < content.length(); i++) {
System.err.print(content.charAt(i));
Thread.sleep(500);//线程休眠至少0.5s
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\n游戏正在开启,请稍后...");
//启动子线程
new Thread(new MyRunnableImpl()).start();
}
static class MyRunnableImpl implements Runnable{
@Override
public void run() {
String content = "游戏正在加载中...";
try {
for (int i = 0; i < content.length(); i++) {
System.err.print(content.charAt(i));
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\n欢迎XXX来到召唤师峡谷");
}
}
}
23.5.3线程的中断(并不会马上中断,而是内部的方法isInterrupted()返回值变成true)
thread.interrupt()//请求中断线程
判断某个线程是否已被发送过中断请求,请使用Thread.currentThread().isInterrupted()方法(因为它将线程中断标示位设置为true后,不会立刻清除中断标示位,即不会将中断标设置为false),而不要使用thread.interrupted()(该方法调用后会将中断标示位清除,即重新设置为false)方法来判断,下面是线程在循环中时的中断方式。
while(!Thread.currentThread().isInterrupted() && 其他条件){
//线程耗时操作
}
注意:如果一个线程处于了阻塞状态(如线程调用了thread.sleep进入阻塞状态),则在线程在检查中断标示时如果发现中断标示为true,则会在 sleep 阻塞方法调用处抛出InterruptedException异常,并且在抛出异常后立即将线程的中断标示位清除,即重新设置为false。抛出异常是为了线程从阻塞状态醒过来,并在结束线程前让程序员有足够的时间来处理中断请求。
public void run() { try { ... /* * 不管循环里是否调用过线程阻塞的方法如sleep,这里还是需要加上 * !Thread.currentThread().isInterrupted()条件,虽然抛出异常后退出了循环,显 * 得用阻塞的情况下是多余的,但如果调用了阻塞方法但没有阻塞时,这样会更安全、更及时。 */ while (!Thread.currentThread().isInterrupted()&& 其他条件) { Thread.sleep(100); //线程耗时操作 } } catch (InterruptedException e) { //线程在sleep期间被中断了,做一些中断后的相关操作... } finally { //线程结束前做一些清理工作 } }
//笔记:
public class InterruptTest {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new MyRunnable());
thread.start();
// sleep是静态方法,在哪个线程中用Thread类名调用的sleep(),则哪个线程休眠
Thread.sleep(3000);// 主线程休眠
// 中断一般是用来停止线程
thread.interrupt();// 主线程中请求中断子线程,请求中断后中断标记置为true;
}
static class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 999999; i++) {
boolean isInter = Thread.currentThread().isInterrupted();//得到当前线程的中断标记后,该中断标记为一直为true;
System.out.println(i + ":" + isInter);
if(isInter){
System.out.println("有人要中断我了...");
System.out.println("isInter:"+Thread.currentThread().isInterrupted());//标记仍是true
break;
}
// boolean interrupted = Thread.interrupted();//得到当前线程的中断标记后,该中断标记置为true后,立即重置为false;
// System.out.println(i + ":" + interrupted);
// if(interrupted){
// System.out.println("有人要中断我了...");
// System.out.println("interrupted:"+Thread.interrupted());//标记被置为false
// break;
// }
}
}
}
}
23.5.4线程的停止
thread.stop();//停止线程
Java API 明确说明,thread.stop()是不安全的。它的不安全主要是针对于二点:释放该线程所持有的所有的锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放,那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。
正确停止线程的解决方法:
class MyThread extends Thread {
private boolean exit = false;
private Thread t;
//外部调用该方法来停止线程,而不推荐调用 stop 方法停止线程。
public void exit() {
exit = true;// 表示为退出状态
t.interrupt();//同时中断子线程,防止线程正在休眠中
//Thread.currentThread().interrupt();// 注意直接这样中断得到的是主线程在请求中断,因为子线程只执行run方法,而这个方法是在主线程中被调用执行,所以得到的当前线程是主线程。
}
@Override
public void run() {
t = Thread.currentThread();
try {
while (!exit && !Thread.currentThread().isInterrupted() && 其他条件) {
Thread.sleep(100);
// 线程耗时操作
}
} catch (InterruptedException e) {
// 线程在sleep期间被中断了,做一些中断后的相关操作...
} finally {
// 线程结束前做一些清理工作
}
}
}