JAVA-基础-线程

35 篇文章 0 订阅

多线程:

进程是系统分配资源的最小单位,线程是系统调度的最小单位,一个进程内的线程之间是可以共享资源的;线程是进程执行的最小单位,也是进程执行的实际单位;线程依附进程进行存活;进程好比工厂,线程好比流水线;进程不能共享资源,线程可以共享资源
每个进程至少有一个线程存在,即主线程;
线程可共享的资源:
1.打开的文件;
2.内存:对象
不可共享的资源:
线程自身的上下文,记账信息,状态不可共享
当线程的数量到达某个合适的值是最好的,如果有太多的线程,就会出现线程之间的争抢和CPU的过度调度问题,而CPU调度是需要消耗系统资源的,所以线程不是越多越好;

那多少线程是最好的?

要看具体的应用场景,密集计算的CPU任务、IO文件读写型任务
当使用场景是计算型任务时,线程的数量等于CPU的数量最好;
进程->线程(轻量化的进程)->协程(轻量化的线程)

查看当前线程的运行状况

首先创建一个线程:
在这里插入图片描述
在jdk自带的终端下进行观测
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建线程的方式:

1.继承Thread类是实现线程的创建线程-2种写法

继承重写Run

在这里插入图片描述

重写thread

在这里插入图片描述

2.实现Runnable接口的方式-3种

传入Runnable

在这里插入图片描述

创建时自带Runnable

在这里插入图片描述

直接重写run方法

在这里插入图片描述

callable接口实现

以上方法都不能拿到线程执行的返回值,
而callable接口可以
在这里插入图片描述

线程休眠:

在这里插入图片描述

面试题:

使用两个线程打印”AABBCCDD“,一个线程只能打印ABCD
创建Runnable任务,传递给两个线程即可;
在这里插入图片描述

线程的常见属性:

  • ID: getId()
  • 名称: getName()
  • 状态: getState()
  • 优先级: getPriority()
  • 是否后台: isDaemon()
  • 是否存活: isAlive()
  • 是否被中断: isInterrupted()
    ID属于每个线程的标识,不同线程不会重复
    名称是各种调试工具
    状态标识当前线程状态
    优先级高的线程更容易被调度
    JVM会再一个进程所有非后台线程结束后,才会结束运行
    存活就是是否线程运行结束了
    关于优先级:
    优先级的取值是1-10;值越大线程的执行权重越高;
    但JVM并不会严格按照优先级顺序执行线程
    线程的类型:
  1. 后台类型-守护线程
  2. 用户线程-创建的默认
    区别:守护线程用于服务用户线程,
    进程退出:没有用户线程时,进程就会结束,无论守护线程是否结束
    守护线程使用场景:JAVA的垃圾回收器;健康检查
    守护线程注意事项:
    1.必须在调用start()前设置;否则报错,且守护线程无效
    2.在守护线程中创建的线程默认是守护线程;

线程的中断:

方式:1.通过共享的标记来进行沟通
2.调用interrupt()方法来通知
关于方式1:
方法1.

public class ThreadDemo {
    private static class MyRunnable implements Runnable {
        public volatile boolean isQuit = false;
        @Override
        public void run() {
            while (!isQuit) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(10 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        target.isQuit = true;
    }
}

方法2.
直接调用interrupt()方法通知该线程停止运行

public class Thread2 {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 两种方法均可以
            while (!Thread.interrupted()) {
            //while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()
                            + ": 有内鬼,终止交易!");
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(10 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        thread.interrupt();
    }
}

重点说明下第二种方法:

  1. 通过 thread 对象调用 interrupt() 方法通知该线程停止运行
  2. thread 收到通知的方式有两种:
    a. 如果线程调用了 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式
    通知,清除中断标志
    b. 否则,只是内部的一个中断标志被设置,thread 可以通过
    1. Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
    2. Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志
    方式2;
    能够更及时的收到通知,即使线程在Sleep也可以收到
    第一种方法
public class ThreadDemo {
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("通过异常收到了中断情况");
            }
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().isInterrupted());
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        thread.start();
        thread.interrupt();
    }
}
通过异常收到了中断情况,收到中断通知,且标志位被清楚

第二种方法

Thread.interrupted()//执行完状态判断之后,将状态复位为false,全局的线程终止后复位
Thread.currentThread().isInterrupted()//只查看当前线程的状态,不改变线程状态
方法解释
public void interrupt()中断对象关联的线程,如果线程阻塞,则以异常的方式通知,否则设置标志位
public static boolean interrupted()判断当前线程中断标志位是否设置,调用后清楚标志位
public boolean isInterrupted()判断对象关联的线程的标志位是否设置,调用后不清除标志位

线程的状态:

在这里插入图片描述

状态解释
NEW新建状态,没有调用start之前的状态
RUNNABLE运行状态,Running执行中,Ready就绪
BLOCKED阻塞状态,
WAITING等待,无明确等待时间
TIME_WAITING超时等待,有明确的等待时间比如sleep
TERMINATED终止状态
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值