java---线程与进程

线程与进程概述

在学习线程之前要先知道什么是进程,进程就是正在运行的程序,它是系统资源调度的独立单位,并且一个进程可以执行多个任务,而线程就是程序执行的任务,它是程序使用CPU的基本单位,因此也可以说线程是依赖于进程的

进程:
是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间

线程:(可分为单线程与多线程)
是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行. 一个进程最少有一个线程
线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干执行路径又可以划分成若干个线程

单线程:
单线程的计算机一次只能做一件事,做的事情单一,也就是程序中只有一条执行路径,效率比较低

多线程:
多线程的计算机可以同时做不同的事情,比如一边听歌,一边打游戏,这两件事虽然感觉起来是在同时发生的事,其实不过是CPU在做着程序之间的高速切换。多线程的存在不是为了提高程序的运行速度,而是为了提高应用程序的使用率,也可以说程序的执行其实都是在抢CPU的资源,也就是抢CPU的执行权,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢到CPU的执行权,但这一过程是随机的,不知道哪一个线程会在哪一个时刻占到这个资源,所以线程的执行有随机性。

线程调度:

分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间

抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),java使用的是抢占式调度

CPU使用抢占式调度模式在多个线程之间进行着高速的切换,对于CPU的一个核心而言,某个时刻,只能执行一个线程,而CPU的在多个线程建切换速度相对于我们的感觉要快,看上去就是在同一个时刻运行,其实,多线程并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高

线程的创建以及启用

线程可以完成一定任务,可以和其它线程共享父进程的共享变量和部分环境,相互协作来完成任务。
线程是独立运行的,其不知道进程中是否还有其他线程存在。
线程的执行是抢占式的,也就是说,当前执行的线程随时可能被挂起,以便运行另一个线程。
一个线程可以创建或撤销另一个线程,一个进程中的多个线程可以并发执行。

线程的创建和启用:

java使用Thread类代表线程,所有的线程对象都必须是Thread或者其子类的实例,每个线程的作用是完成一定任务,实际上是就是执行一段程序流(一段顺序执行的代码)

方法一、继承Thread类创建线类
1:定义Thread类的子类 并重写该类的Run方法 该run方法的方法体就代表了线程需要完成的任务
如下:

public class MyThread extends Thread{


    /**
     * run方法就是线程要执行的任务方法
     */
    @Override
    public void run(){
        //这里的代码 就是一条新的执行路径
        //这个执行路径的触发1方式,不是调用run方法,而是通过Thread对象的start()来触发
        for (int i=0;i<5;i++){
            System.out.println("白茶清欢无别事"+i);
        }

    }

2:创建Thread类的实例,即创建了线程对象
3:调用线程的start方法来启动线程

举例说明

public class Demo1 {
    public static void main(String[] args) {
    //创建Thread对象
        MyThread thread =  new MyThread();
        //调用线程的start方法来启动线程
        thread.start();
        //自定义输入
        for (int i=0;i<5;i++){
            System.out.println("我在等风也等你"+i);
        }
    }
}

运行效果如图:
在这里插入图片描述

使用Runnable接口创建线程类
1:定义Runnable接口的实现类,并重写它的Run方法,run方法同样是该线程的执行体!

定义Runnable接口的实现类:

public class MyRunnable implements Runnable {
    @Override
    //线程的任务
    public void run() {
        for (int i=0;i<5;i++){
            System.out.println("窗前明月光"+i);
        }

    }
}

2:创建Runnable实现类的实例,并将此实例作为Thread的target创建一个Thread对象,该Thread对象才是真正的线程对象!
3:调用start方法启动该线程

/**
 * 多线程技术
 * 实现Runnable 与 继承Thread相比有如下优势
 * 1、通过创建任务,然后给线程分配的方式来实现的多线程,更适合多个线程同时执行
 * 2、可以避免单继承带来的局限性
 * 3、任务与线程是分离的,提高了程序的健壮性
 * 4、后续学习的线程池技术,接受Runnable类型,不接收Thread类型
 */

public class Demo2 {
    public static void main(String[] args) {
        //实现Runnable
        //1、 创建一个任务对象
        MyRunnable r = new MyRunnable();
        //2、 创建一个线程,并为其分配一个任务
        Thread t = new Thread(r);
        //3、 执行这个线程
        t.start();
        for (int i=0;i<5;i++){
            System.out.println("举头望明月"+i);
        }

    }
}

运行效果:
在这里插入图片描述

方法三:匿名内部类实现线程

public class Demo3 {
    public static void main(String[] args) {
        //匿名内部类实现线程
        new Thread(){
            @Override
            public void run(){
                for (int i=0;i<5;i++){
                    System.out.println("想太多了"+i);
                }
            }
        }.start();

        for (int i=0;i<5;i++){
            System.out.println("加油吧,少年!"+i);
        }
    }
}

运行效果如图:
在这里插入图片描述

多线程的常用方法

setName​(String name) 将此线程的名称更改为等于参数 name
getName() 返回此线程的名称
currentThread() 返回对当前正在执行的线程对象的引用

事例如下:

public class Demo4 {
    public static void main(String[] args) {
        //如何获取线程的名字
        new Thread(new MyRunnable()).start();
        //在new的时候传入线程名称,或者用setName方法
        new Thread(new MyRunnable(),"锄禾日当午").start();
        new Thread(new MyRunnable()).start();

    }
    static class MyRunnable implements Runnable{
        @Override
        public void run(){
            //获取当前正在运行的线程的名称
            System.out.println(Thread.currentThread().getName());
        }
    }
}

运行效果:
在这里插入图片描述

sleep​(long millis) 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性。
sleep​(long millis, int nanos) 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数加上指定的纳秒数,具体取决于系统定时器和调度程序的精度和准确性。

事例如下:

public class Demo5 {
    public static void main(String[] args) throws InterruptedException {
        //线程休眠 sleep
        for (int i=0;i<8;i++){
            System.out.println(i);
            //抛出异常
            //sleep两种方法调用
            //1、导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性
            //2、导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数加上指定的纳秒数,具体取决于系统定时器和调度程序的精度和准确性
            Thread.sleep(1000);
        }
    }
}

interrupt() 中断此线程。
interrupted() 测试当前线程是否已被中断

事例如下:

/**
 * 线程的中断
 */
public class Demo6 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new MyRunnable(),"哈哈哈");
        t1.start();
        for (int i=0;i<5;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
            Thread.sleep(1000);
        }
        //中断此线程 t1
        t1.interrupt();

    }
    static class MyRunnable implements Runnable{

        @Override
        public void run() {
            for (int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                     //e.printStackTrace();
                    System.out.println("发现中断标记!");
                    //发现中断标记之后,若想要线程中断,可以用return,返回run方法
                    return;
                }
            }
        }
    }

}


运行效果如下:
在这里插入图片描述

setDaemon​(boolean on) 将此线程标记为 daemon线程或用户线程

示例如下:

/**
 * 守护线程 :用于守护用户线程,当最后一个用户线程结束时,所有守护线程自动死亡
 * 用户线程:当一个进程不包含任何一个存活的用户线程时,进行结束
 *
 *
 */

public class Demo7 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Demo6.MyRunnable(),"哈哈哈");
        //设置t1为守护线程,true为守护线程
        t1.setDaemon(true);
        t1.start();
        for (int i=0;i<5;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
            Thread.sleep(1000);
        }


    }
    static class MyRunnable implements Runnable{

        @Override
        public void run() {
            for (int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    /*System.out.println("发现中断标记!");
                    //发现中断标记之后,若想要线程中断,可以用return,返回run方法
                    return;*/
                }
            }
        }
    }

}

isAlive()方法的功能是判断当前的线程是否处于活动状态

示例如下:

class Mythread extends Thread{
     
    @Override
    public void run() {
        System.out.println("run =="+this.isAlive());
    }
     
}
 
public class Test01 {
 
    public static void main(String[] args) {
        Mythread thread=new Mythread();
        System.out.println("begin =="+thread.isAlive());//①
        thread.start();//②
        System.out.println("end =="+thread.isAlive());//③
    }
     
}
 
结果:
begin ==false
end ==true
run ==true

方法isAlive()的作用是测试线程是否处于活动状态。那么什么情况下是活动状态呢?活动状态就是线程已经启动且尚未停止。线程处于正在运行或准备开始运行的状态,就认为线程是存活的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值