浅谈Thread和Runnable

浅谈Thread和Runnable

本文介绍Thread和Runnable创建线程的区别:

-两种创建线程方法的比较
-线程的生命周期
-线程的守护神-守护线程
- 总结
- 守护线程的代码


线程创建的两种方式比较:
  • 继承Thread类创建多线程:
   public class MyThread extends Thread{
         @Override
               public void run(){
                   ...
            }
        }
        MyThread  t = new MyThread();
        t.start();
  • 实现Runnable接口:
 class MyThread implements Runnable{
     @Override
     public void run(){
         ....
     }
   }
MyThread mt = new MyThread ();
Thread t = new Thread(mt);
t.start();
  • 两种方式的比较:实现Runnable接口方式可以避免继承Thread方式由于Java单继承特性带来的缺陷。实现Runnable的代码可以被多个线程共享,适合于多个线程处理同一资源的情况.(具体见代码)
线程的生命周期:
  • 线程的生命周期中有几种状态,如下图:
    这里写图片描述
  • 创建状态:新建一个线程对象。如:Thread td = new Thread();
  • 就绪状态:创建了线程对象后,调用线程的start()方法(注意:此时线程只是进入了线程队列,等待获取CPU服务,具备了运行的条件,但并不一定已经开始运行了。)
  • 运行状态:处于就绪状态的线程,一旦获取了CPU资源,便进入到运行状态,开始执行run方法的逻辑。
  • 终止状态:线程的run方法执行完毕,或者线程调用了stop方法,线程进入终止状态。
  • 阻塞状态:一个正在执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入了阻塞状态,如调用了sleep方法。

    线程的守护神
  • Java线程有两类:用户线程和守护线程。用户线程:运行在前台,执行具体的任务。守护线程:运行在后台,为前台线程服务。特点:一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作。应用:数据库连接池中的监测线程、JVM虚拟机启动后的监测线程、垃圾回收线程。

  • 如何设置守护线程:可以通过Thread类的setDaemon(true)方法来设置当前线程为守护线程。注意事项:setDaemon(true)方法必须在start()方法前调用,否则会抛出IllegalThreadStateException异常。
  • 在守护线程中产生的线程也是守护线程。
  • 不是所有的操作都能分配给守护线程来执行,比如读写操作或者计算逻辑。理解:假如读写操作是守护线程,当读写操作执行到一半,所有的用户线程都结束了,守护线程会随着JVM一起结束工作。守护线程执行的读写操作还没完成,程序有异常。后面有程序讲解
  • 使用jstack生成线程快照:生成当前时刻线程的快照,即当前进程中所有线程的信息。帮助定位程序出现的原因。
  • jstack的使用:具体如下图
    这里写图片描述

  • 第二个参数pid对应的就是进程的进程id。使用如下图:
    这里写图片描述

    总结:
  • 首先,本文介绍了Thread和Runnable创建线程的区别。

  • 介绍了线程的生命周期和周期对应的代码和状态。
  • 再次介绍了守护线程的概念和jstack工具。

    守护线程的代码:
    /**
    *创建一个守护线程,实现每一秒钟向文件写入一句话
    *
    */
    public class GuardThread implements Runnable{
       @Override
       public void run(){
                System.out.println("守护线程:"+Thread.currentThread().getName()+"开始执行");
        wirterFile();
        System.out.println("守护线程:"+Thread.currentThread().getName()+"结束执行");
       }
      /**
     * 每一秒钟向文件中写入一句话
     * @throws Exception
     */
    private void wirterFile(){
                   OutputStream fileOutPutStream = null;
        try {
    
            File daemonFile = new File("D:"+File.separator+"daemon.txt");
            //第二个参数表示已追加的形式来写文件
            fileOutPutStream = new FileOutputStream(daemonFile,true);
    
            int count = 0;
            while(count<1000){
                fileOutPutStream.write(("word "+count+"\r\n").getBytes());
                System.out.println("守护线程:"+Thread.currentThread().getName()+"写入 word "+count++);
                /**
                 * 每写一次文件休眠一秒
                 */
                Thread.sleep(1000);
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            if(fileOutPutStream!=null){
                try {
                    fileOutPutStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        }
    }  
/*
*主线程类
*/
public class GuardThreadTest {
     public static void main(String[] args) {

        System.out.println("主线程"+Thread.currentThread().getName()+"开始执行");

        GuardThread guardThread = new GuardThread();
        Thread td = new Thread(guardThread);
        //设置线程为守护线程
        td.setDaemon(true);
        //启动线程
        td.start();

        Scanner scanner = new Scanner(System.in);
        //主线程阻塞 等待键盘输入
        String keyWord = scanner.next();

        System.out.println("主线程"+Thread.currentThread().getName()+"结束执行,键盘上输入的字:"+keyWord);
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值