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 {
            // 线程结束前做一些清理工作
        }
    }
}

results matching ""

    No results matching ""