Thread Runnable线程及stop、interrupt、sleep等方法讲解

时间:2025-04-18 06:59:27
  • 如何开启线程

开启线程2种方式:

自定义类继承Thread类,重写run方法;new 自定义类().start()

自定义类实现Runnable接口,实现run方法;new Thread(new 自定义类()).start()

  • Thread和Runable

Thread是对线程的抽象封装,完成独立完成某个任务的调度,包括任务的开始、暂停、结束等操作。本身是实现Runnable接口,所以具有Runnable的所有功能。

Runnable 是对任务的抽象封装,业务任务的具体逻辑封装。本身不具有独立资源调度。需要Thread协助完成,这也就是前面说的开启线程需要先new Thread() 通过参数把Runnable传递进去。

  • JVM开启,默认开启哪些线程(JDK1.8为例)
public static void main(String[] args) {
        //虚拟机线程系统的管理接口(JVM开启的线程);对JVM系统进行监控时,使用类ManagementFactory
        ThreadMXBean threadMXBean= ();
        ThreadInfo[] threadInfos = (false, false);
        for(ThreadInfo threadInfo:threadInfos){
            ("["+()+"]"+());
        }
        /* 一般项目启动会启动的线程有:
        * [8]JDWP Command Reader
        [7]JDWP Event Helper Thread
        [6]JDWP Transport Listener: dt_socket
        [5]Attach Listener
        [4]Signal Dispatcher
        [3]Finalizer  线程管理Object finalize()方法,每个对象销毁时都会调用这个方法;不推荐在这个方法中写资源释放,有时调用不到(main结束这个线程也就没有了)
        [2]Reference Handler
        [1]main 主线程,线程关闭其他线程会依次关闭
        * */
    }
  • stop/interrupt/sleep等方法总结

stop():结束线程,比较野蛮会立即结束线程。比如当前线程正在写一个文件,或者正在写入数据库,正在完成一半任务时,接到stop命令,立即线程结束,导致文件不完整,错误的文件或数据库数据不完整等问题。所以JDK1.8之后不在推荐使用。当然如果能够保证当前线程没有这些类似任务,采用stop停止线程也是可以的。

interrupt():标记线程状态为中断状态(线程本身并不会结束),此时线程中如果有join、wait、sleep等方法调用的时候会抛出异常。在线程的run()方法中我们需要自己写逻辑结束线程。isInterrupt()可获取线程的中断状态。()静态方法内部会调用当前线程的isinterrupt()方法,但是内部也会再次把状态标志位修改,所有一般都是用实例interrupt方法。对于Runnable实例化的线程,一般用().interrupt() 方法判断。

sleep():使当前线程进入阻塞状态。同时这个方法内部会监测interrupt状态,如果当前线程中断后,同时线程还睡眠时,会报异常: sleep interrupted。sleep()并不会释放对象锁,只有锁代码块执行完后,其他线程才能够获取锁

  • 线程stop方法案例
import ;

/**
 * @ClassName xu01
 * @Description des
 * @Author zyk
 * @Date 2019/9/24
 * @Version 1.0
 **/
public class xu01 {
    private static class UseThread extends Thread{
        @Override
        public void run() {
            while(true) {
                ("正在写入文件,写入部分...");
            }
        }
    }

    public static void main(String[] args) {
        UseThread useThread=new UseThread();
        ();
        //main线程睡眠20
        try {
            (20);
        } catch (InterruptedException e) {
            ();
        }
        //main线程2秒后关闭
        // 1:stop() 是一个@Deprecated不推荐使用,过于野蛮停止线程(会出现线程写部分文件就挂了)
        ();

        ("main 线程结束");
    }
}
  • 线程interrupt方法案例
import ;

/**
 * @ClassName xu01
 * @Description des
 * @Author zyk
 * @Date 2019/9/24
 * @Version 1.0
 **/
public class xu01 {
    private static class UseThread extends Thread{
        @Override
        public void run() {
            while(true) {
                ("正在写入文件,写入部分...");
                //判断线程状态是否,是否需要结束
                //                if(isInterrupted()){
                //静态方法也是同样的功能,内部会获取当前线程
                if(()){
                    ("线程状态:"+interrupted());
                    ("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");
                    break;
                }

            }
        }
    }

    public static void main(String[] args) {
        UseThread useThread=new UseThread();
        ();
        //main线程睡眠20
        try {
            (20);
        } catch (InterruptedException e) {
            ();
        }
        //main线程2秒后关闭
        //只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束
        ();
        ("main 线程结束");
    }
}
  • 线程sleep方法案例

在线程中添加sleep睡眠逻辑,做完一件事后睡眠一段时间,再次做事情。

import ;

/**
 * @ClassName xu01
 * @Description des
 * @Author zyk
 * @Date 2019/9/24
 * @Version 1.0
 **/
public class xu01 {
    private static class UseThread extends Thread{
        @Override
        public void run() {
            while(true) {
                ("正在做某件任务...");
                ("结束一段任务后,线程睡眠一段时间");

                try {
                    (20);
                } catch (InterruptedException e) {
                    ();
                }

                if(()){
                    ("线程状态:"+interrupted());
                    ("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");
                    break;
                }

            }
        }
    }

    public static void main(String[] args) {
        UseThread useThread=new UseThread();
        ();
        //main线程睡眠20
        try {
            (20);
        } catch (InterruptedException e) {
            ();
        }
        //main线程2秒后关闭
        //只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束
        ();
        ("main 线程结束");
    }
}

注意:这样线程并不会结束,运行结果如下

正在做某件任务...
结束一段任务后,线程睡眠一段时间
: sleep interrupted
	at (Native Method)
	at (:340)
	at (:386)
	at .xu01$(:21)
main 线程结束
正在做某件任务...
结束一段任务后,线程睡眠一段时间
正在做某件任务...
结束一段任务后,线程睡眠一段时间

这是因为 (20);会抛出异常后,把当前线程中断状态又改回去了,导致线程还会继续执行。

需要修改代码:第一种方式,在sleep方法上添加try-catch,在InterruptedException异常代码块中再次调用interrupte()方法。第二种方式,把while死循环监视起来,出现InterruptedException 异常后结束线程,修改后代码如下:

import ;

/**
 * @ClassName xu01
 * @Description des
 * @Author zyk
 * @Date 2019/9/24
 * @Version 1.0
 **/
public class xu01 {
    private static class UseThread extends Thread{
        @Override
        public void run() {
            try {
                while (true) {
                    ("正在做某件任务...");
                    ("结束一段任务后,线程睡眠一段时间");

                    try {
                        (20);
                        //: sleep interrupted 需要把这个异常抛出去
                    } catch (InterruptedException e) {
                        //interrupt();
                        throw e;
                    }

                    if (()) {
                        ("线程状态:" + interrupted());
                        ("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");
                        break;
                    }

                }
            }catch (InterruptedException e){
                ();
                ("子线程结束");
            }
        }
    }

    public static void main(String[] args) {
        UseThread useThread=new UseThread();
        ();
        //main线程睡眠20
        try {
            (20);
        } catch (InterruptedException e) {
            ();
        }
        //main线程2秒后关闭
        //只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束
        ();
        ("main 线程结束");
    }
}
  • 线程池使用

JDK1.8不在推荐使用Executors创建线程了,推荐使用ThreadPoolExecutor,可控制最大线程数量。而Executors 最多创建线程数量是 Integer.MAX_VALUE 会导致系统OOM问题

public static void main(String[] args) throws ExecutionException, InterruptedException {
        int count=230;
        //线程池1:
        ExecutorService pool1=();
        ExecutorService pool2=(5);

        //线程池2:
        ThreadFactory namedThreadFactory=new ThreadFactoryBuilder()
                .setNameFormat("jake-pool-%d")
                .build();
        ExecutorService pool=new ThreadPoolExecutor(5,200,
                60L,,new LinkedBlockingQueue<Runnable>(1024),
                namedThreadFactory,new ());
        for(int i=0;i<count;i++){
            (()->{
                ("========线程名称:"+().getName());
            });
        }
        ();
        ("shutdown");

    }