(一) 多线程基础

1.进程和线程区别

多进程:在操作系统中能同时运行多个任务(程序)。如电脑: 微信和网易云音乐同时运行
多线程:在同一应用程序中有多个顺序流在执行。如网易云音乐:音乐播放和歌词显示同时进行
并发:同一时间段中几个程序在同一个处理机上运行,但任一时刻点上只有一个程序在运行。
并行:同一时刻点多个程序在多个处理机上独立异步的运行。

多线程是异步的,代码的运行结果与代码执行(调用)顺序是无关的

2.实现多线程方式

在Java中实现多线程有两种手段,一种是继承Thread类,另一种就是实现Runnable接口。

(1) 继承Thread类
public class ThreadI extends Thread {

    @Override
    public void run() { 
       System.err.println("运行新线程!");
    }
    public static void main(String[] args) {
        ThreadI threadM = new ThreadI();
        // 启动新线程执行run()方法,新线程与主线程并行执行
        threadM.start();     
        System.out.println("运行主线程!");
    }
}
(2) 实现Runable接口
public class RunnableI implements Runnable {
    
    @Override
    public void run() {
        System.err.println("运行新线程!" );
    }
    public static void main(String[] args) {
        RunnableI  runnableI = new RunnableI();  
        Thread threadX = new Thread(runnableI);
        // 启动新线程执行run()方法,新线程与主线程并行执行
        threadX.start();
        System.out.println("运行主线程!" );
    }
}

start()方法通知"线程规划器"此线程已经准备就绪,等待系统安排时间来调用Thread中的run()方法。执行start()方法的顺序不代表线程启动的顺序!

3.线程方法
(1) currentThread()

返回当前调用程序的线程信息

返回线程的名称
Thread. currentThread().getName();
返回线程的唯一标识
Thread. currentThread().getId();

Thread.currentThread()与this的区别
当线程不作为参数传入另一个线程时,this和Thread.currentThread() 代表的是同一个对象。
线程作为参数传入时,this指向传入对象,即内部线程,而Thread.currentThread()指向调用当前方法的线程对象,即外部线程。

public class ThreadIV extends Thread {

    @Override
    public void run() {
        System.out.println("run name: " + Thread.currentThread().getName());
        System.out.println("run this: " + this.getName());  // this对象指向threadIV
    }
}

class ThreadVI {
    public static void main(String[] args) {
        ThreadIV threadIV = new ThreadIV();
        Thread thread = new Thread(threadIV);
        thread.setName("A");
        thread.start();
    }
}

运行结果:

run name: A
run this: Thread-0

源码分析:

ThreadIV threadIV = new ThreadIV();将Runnable对象保存并初始化线程名称:Thread-N;
在这里插入图片描述
thread.start(); 启用线程调用run方法,执行时判断Runnable对象是否存在,调用对象的run()方法
在这里插入图片描述

(2) isAlive()

判断线程是否处于活动状态(已经启动且尚未终止)

(3) sleep()

使当前正在执行的线程休眠(不释放锁,单位:ms) 用法:Thread.sleep(10);

(4) 停止线程
① interrupt()

interrupt() 方法是在Thread对象线程中打停止标记,并不会真的停止线程

② interrupted()

interrupted() 静态方法是测试当前线程(运行该方法的线程)是否已经中断

测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。

③ isInterrupted()

isInterrupted() 方法是测试线程Thread对象是否已经是中断状态,但不清除状态标志

④ 异常/Return中断线程

调用执行interrupt()方法,根据interrupted() 方法返回的Boolean,执行throw new InterruptedException()或return;即可实现中断线程

注意:如果线程在sleep() 状态下调用interrupt()方法,则会进入catch语句,并清除停止状态值,使之变成false。

注意:

Thread对象的stop()方法:暴力停止线程(方法已废弃)
出现问题:可能出现对锁定对象释放锁,造成数据异常
Thread对象的suspend()方法暂停线程;resume()方法恢复线程的执行。
出现问题:1.造成公共的同步对象的独占,使其他线程无法访问公共同步对象
                 2.出现因为线程的暂停而导致数据不同步的情况

(5) yield()

yield()方法是放弃当前的CPU资源,将其让给其他的任务去去占用CPU执行时间。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

sleep()和yield()的区别:sleep()使当前线程进入停滞状态,执行sleep()的线程在指定的时间(由程序设定的)内肯定不会被执行;yield()只是使当前线程重新回到可执行状态(放弃当前的CPU资源),执行yield()的线程有可能在进入到可执行状态后马上又被执行。

4.线程优先级

CPU优先执行优先级较高的线程对象中的任务
调用Thread对象的setPriority()方法;优先级分为1~10共10个级别,默认优先级为5

线程优先级具有继承性:比如A线程启动B线程,则B线程的优先级与A是一样的。
线程优先级具有规则性:优先级高的线程总是大部分优先执行,但不代表优先级高的线程绝对优先执行。
线程优先级具有随机性:优先级较高的线程不一定总是先执行完

5.守护线程

线程分为用户线程和守护线程;守护线程是一种特殊的线程,当进程中不存在用户线程,则守护线程自动销毁;典型的守护线程:垃圾回收线程。设置守护线程:调用Thread对象的setDaemon(true) 方法

6.线程状态

线程对象在不同的运行时期有不同的状态,状态定义:State枚举类型。在调用与线程有关的方法后,会进入不同的线程状态。

NEW状态是线程实例化未执行start()方法时的状态
RUNNABLE状态是线程进入运行的状态
TERMINATED是线程被销毁时的状态
TIMED_WAITING是线程执行了sleep方法状态
BLOCKED是某一个线程在等待锁时状态
WAITING是线程执行了wait方法后的状态

public class ThreadIII extends Thread {

    @Override
    public void run() {
        System.out.println("预计状态:RUNNABLE = " + Thread.currentThread().getState());
    }
}

public class RunMain {
    public static void main(String[] args) throws InterruptedException {
        ThreadIII threadA = new ThreadIII();
        System.out.println("预计状态:NEW = " + threadA.getState());
        threadA.start();
        Thread.sleep(100);
        System.out.println("预计状态:TERMINATED = " + threadA.getState());
    }
}

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

7.线程组

可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程。线程组可以批量的管理线程或线程组对象,有效地对线程或线程组对象进行操作(JVM根线程组是system)。

public class RunMain {
    public static void main(String[] args) {
        ThreadVI threadVI = new ThreadVI();
        ThreadIV threadIV = new ThreadIV();
        ThreadGroup group = new ThreadGroup("线程组α");
        Thread threadA = new Thread(group, threadVI);
        Thread threadB = new Thread(group, threadIV);
        threadA.start();
        threadB.start();
        System.out.println("活跃线程数:" + group.activeCount());
        System.out.println("线程组名称:" + group.getName());
    }
}

在实例化ThreadGroup线程组x时如果不指定所属的线程组,则x线程组自动归到当前线程对象所属的线程组中。

当调用线程组ThreadGroup的 Interrupt方法时,可以将该组中的所有正在运行的线程批量停止。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值