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

  • 如何开启线程

开启线程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= ManagementFactory.getThreadMXBean();
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        for(ThreadInfo threadInfo:threadInfos){
            System.out.println("["+threadInfo.getThreadId()+"]"+threadInfo.getThreadName());
        }
        /* 一般项目启动会启动的线程有:
        * [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等方法调用的时候会抛出异常java.lang.InterruptedException。在线程的run()方法中我们需要自己写逻辑结束线程。isInterrupt()可获取线程的中断状态。Thread.interrupt()静态方法内部会调用当前线程的isinterrupt()方法,但是内部也会再次把状态标志位修改,所有一般都是用实例interrupt方法。对于Runnable实例化的线程,一般用Thread.currentThread().interrupt() 方法判断。

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

  • 线程stop方法案例
import java.util.concurrent.TimeUnit;

/**
 * @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) {
                System.out.println("正在写入文件,写入部分...");
            }
        }
    }

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

        System.out.println("main 线程结束");
    }
}
  • 线程interrupt方法案例
import java.util.concurrent.TimeUnit;

/**
 * @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) {
                System.out.println("正在写入文件,写入部分...");
                //判断线程状态是否,是否需要结束
                //                if(isInterrupted()){
                //Thread.interrupted静态方法也是同样的功能,内部会获取当前线程
                if(Thread.interrupted()){
                    System.out.println("线程状态:"+interrupted());
                    System.out.println("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");
                    break;
                }

            }
        }
    }

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

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

import java.util.concurrent.TimeUnit;

/**
 * @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) {
                System.out.println("正在做某件任务...");
                System.out.println("结束一段任务后,线程睡眠一段时间");

                try {
                    TimeUnit.MILLISECONDS.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

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

            }
        }
    }

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

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

正在做某件任务...
结束一段任务后,线程睡眠一段时间
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at java.lang.Thread.sleep(Thread.java:340)
	at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
	at controller.multithread.xu01$UseThread.run(xu01.java:21)
main 线程结束
正在做某件任务...
结束一段任务后,线程睡眠一段时间
正在做某件任务...
结束一段任务后,线程睡眠一段时间

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

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

import java.util.concurrent.TimeUnit;

/**
 * @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) {
                    System.out.println("正在做某件任务...");
                    System.out.println("结束一段任务后,线程睡眠一段时间");

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

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

                }
            }catch (InterruptedException e){
                e.printStackTrace();
                System.out.println("子线程结束");
            }
        }
    }

    public static void main(String[] args) {
        UseThread useThread=new UseThread();
        useThread.start();
        //main线程睡眠20
        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //main线程2秒后关闭
        //只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束
        useThread.interrupt();
        System.out.println("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=Executors.newCachedThreadPool();
        ExecutorService pool2=Executors.newFixedThreadPool(5);

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

    }

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您介绍一下线程的创建与撤销的基本方法,以Java语言为例。 线程的创建: 在Java中,有两种方式可以创建线程: 1. 继承Thread类,并重写run()方法。 2. 实现Runnable接口,并重写run()方法。 以下是使用第二种方式创建线程的示例代码: ``` class MyThread implements Runnable { public void run() { System.out.println("This is a new thread."); } } public class ThreadDemo { public static void main(String[] args) { MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start(); } } ``` 线程的撤销: Java中可以使用stop()方法来撤销线程,但该方法已被废弃,因为它可能会导致线程意外终止,从而导致应用程序的不稳定性。Java建议使用interrupt()方法来请求线程停止。 以下是使用interrupt()方法停止线程的示例代码: ``` class MyThread implements Runnable { public void run() { while(!Thread.currentThread().isInterrupted()) { System.out.println("This is a new thread."); } System.out.println("Thread is stopped."); } } public class ThreadDemo { public static void main(String[] args) { MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } } ``` 在上述代码中,MyThread类的run()方法中,使用了isInterrupted()方法检查线程是否被请求停止。在主线程中,使用interrupt()方法请求线程停止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值