线程的创建的Thread和Runnable方法

本文详细介绍了Java中实现多线程的两种方式:继承Thread类和实现Runnable接口,并通过代码示例展示了这两种方法。同时,解释了线程的状态转换以及如何操作线程,包括设置优先级、休眠等。此外,还讨论了守护线程的概念及其特点。
摘要由CSDN通过智能技术生成

一些概念

程序:为了某个特定的任务,用某种语言编写的一组指令,就是一段静态的代码

进程:程序一次执行过程,是一个动态的过程:  有开始  存在 和死亡---所谓的生命周期( 在此简写了生命周期的过程 )

线程:进程可以分为多个线程(对于进程内部的线程切换,不需要经过cpu,减少了系统调度的时间,提高了效率)

引入进程的目的:更好地使用多道程序并发执行,提高资源利用率和系统吞吐量
引入线程的目的:减少程序在并发执行时所付出的时空开销,提高操作系统的并发性能

线程是一个基本的cpu执行单元,也是程序被执行的最小单元,它是进程的一个实体,是被系统独立调度和分派的基本单位,
自己不拥有系统资源,只拥有一点在运行时必不可少的资源,与同属一个进程的其他线程共享进程所拥有的资源

引入线程之后,进厂只作为除cpu外的系统资源的分配单元(分配资源),线程作为处理机(cpu)的分配单位(执行)

java如何实现多线程:
方法一:

  1. 写一个自定义类型 继承 Thread(线程类)
  2. 重写run()
  3. 创建对象
  4. .启动线程: start()

上代码:


public class ThreadDemo01 {
        public static void main(String[] args) {
            //创建多个线程
            ThreadTest tt=new ThreadTest();
            ThreadTest tt1=new ThreadTest();
            /*
            1.启动线程:start()
            2.在启动线程之后,自动调用run()
             */
            //手动启动线程
            tt.start();
            tt1.start();
        }
}
//Thread在java中用来表示线程类的,里面包含了线程运行过程的方法run()
//需要当前线程运行执行什么操作就在run方法中写上就可以了,
class ThreadTest extends Thread{
    int i=10;//虽然i是全局变量,但是tt和tt1是两个对象,数据没办法共享
    @Override
    public void run(){
        for (; i >= 0 ; i--) {
            System.out.println("进程名字:"+getName()+"\t进程id:"+getId()+":"+i);
        }
    }
}

在这里插入图片描述
介绍两个方法:
getName():获取进程名字
getId():获取进程id

方法一的弊端:

  1. java中的继承只能单继承,所以创建的对象只能继承一个Thread,限制了类的继承
  2. 每个对象都是一个单独的线程,线程之间不能实现资源共享

方法二(第一种方式):
实现接口:(Runnable)

  1. 写一个类实现Runnable接口
  2. 重写run方法
  3. 创建实例
  4. 调用start()

上代码:


public class ThreadDemo02 {
    public static void main(String[] args) {
        //3.创建实例
        //3.1创建Runnable实例
        RunnableTest rt=new RunnableTest();

        //不管创建多少次,都是根据rt创建的,所有是共用一个RunnableTest实例
        Thread t=new Thread(rt);
        Thread t1=new Thread(rt);
        t.start();
        t1.start();
    }

}
//runnable里面有个抽象方法需要重写
class RunnableTest implements Runnable{
    int i=10;
    //重写run方法
    @Override
    public void run() {
        for (; i >=0 ; i--) {
            //currentThread()获取当前线程
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

在这里插入图片描述

优势:

  1. 实现了Runnable接口继承Thread接口比继承Thread所具有的优势
  2. 可以避免java中类的单一继承限制
  3. 增加程序强壮性,代码可以被多个线程所共享
  4. 适合多个相同的程序代码线程处理同一个资源
  5. 线程池只能放入实现Runnable接口的线程,不能放直接放继承Thread的线程

发现了有些重复出现了,可以思考思考为什么会出现这种情况

方法二(第二种方式):我称之为变异(变种)

  1. Thread构造需要Runnable参数
  2. Runnable是一接口
  3. 创建RunnableTest类型实现接口Runnable
  4. 创建RunnableTest对象传入Thread

这是第一种方式,我们还可以通过匿名内部类来创建接口对象
注意:创建的匿名内部类来实现Runnable接口,资源是不可以共享的


public class ThreadDemo03 {
    //第二种方式的变种
    public static void main(String[] args) {
        //匿名内部类,数据不可以共享
         Thread t=new Thread(){
            @Override
            public void  run(){
                for (int i = 0; i <5 ; i++) {
                    System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        };
        Thread tt=new Thread(){
            @Override
            public void  run(){
                for (int i = 0; i <5 ; i++) {
                System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        };
        t.start();
        tt.start();
    }
}

在这里插入图片描述

线程的几种状态

  1. 新建状态(new):当使用new关键字创建线程实例后,该线程就处于就创建状态,但不会执行 Thread t=new Thread();
  2. 继续状态:当调用start()方法,该线程就处于就绪状态,表示可以执行,但不会一定立即执行,而是等待cpu分配时间片进行处理
  3. 运行状态:当cpu为该线程分配时间片,执行该线程run()时,线程处于运行状态
  4. 暂停状态(休眠,等待,堵塞):当线程调用sleep或者wait或者io阻塞,主动放弃cou时间片,就进行暂停状态
  5. 死亡:当线程run方法执行完,或者抛出异常,线程就死亡了

操作线程常见方法

  1. 休眠:static void sleep(long millis);是当前线程休眠指定的毫秒值
  2. 设置关于优先级:setPriority(int 优先级别1-10) 设置线程的优先级 优先级越高,获得cpu几率越大,不一定被选中 (1-10 1最低 5默认 10最高)
  3. 设置名字:setName(String name)
  4. 获取名字:getName()
  5. 获取id:getId()

上代码:

public class ThreadDemo05 {
    public static void main(String[] args) throws InterruptedException {
//        for (int i = 0; i <10 ; i++) {
//            Thread.sleep(1000);
//            System.out.println(i);
//        }
        ThreadTest tt1=new ThreadTest();
        tt1.setPriority(10);
        //默认优先级为5
        ThreadTest tt2=new ThreadTest();
        ThreadTest tt3=new ThreadTest();
        tt3.setPriority(1);

        tt1.start();
        tt2.start();
        tt3.start();
    }
}

设置守护线程

守护线程也就是后台线程,默认创建的都是普通线程
守护线程是通过方法设置将普通方法转变为守护线程
守护线程使用上与普通线程没有区别,区别在结束时间上
当一个进程中所有的普通线程都接结束后,进程就结束了
此时你的守护线程会被强制杀掉
setDaemo()

一个有点意思的代码:有条件可以运行一下


public class ThreadDemo06 {
    public static void main(String[] args) {
        Thread thread=new Thread() {
            public void run(){
                for (int i = 0; i < 5; i++) {
                    System.out.println("ros:jack,我要跳了");

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("ros:jack,快来守护我");
                System.out.println("ros:poling");
            }
        };
        Thread thread1=new Thread(){
            @Override
            public void run() {
                while(true){
                    System.out.println("jack:ros,你跳我也跳");
                    try {
                        Thread.sleep(1500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread.start();
        //jack启动之前,将它设置为守护线程
        thread1.setDaemon(true);
        thread1.start();
    }
}

分想到此结束,希望在此你有满满的收获,
如果有错误的地方,麻烦请指点指点!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值