Java多线程(1)

1、线程和进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。所有运行中的任务通常就是一个进程,当一个程序进入内存运行时,即变成一个进程。进程是处于运行过程中的程序。

进程的三个特征:
  1. 对立性:进程是系统中独立存在的实体,它可以拥有自己独立的资源。每个进程都有自己私有的地址空间
  2. 动态性:程序是一个静态的指令集合,进程是一个正在系统中活动的指令集合。
  3. 并发性:多个进程可以在单个处理器上并发执行,多个进程之间互不影响。

2、线程的创建和启动

2.1、继承Thread类创建线程类

通过继承Thread类来创建并启动多线程的步骤
1、定义Thread的子类,并重写run()方法,该方法就是线程执行体。
2、创建Thread子类的实例
3、调用线程对象的start()方法来启动该线程,不论使用什么方式创建线程,启动都是调用start()方法

package usethread;

public class FirstThread extends Thread {
    private int i;
    //重写run()方法,run()方法的方法体就是线程执行体
    public void run() {
        for(; i < 10; i++) {
            //当线程继承Thread类时,直接使用this即可获取当前线程
            System.out.println(this.getName() +" " + i);
        }
    }

    public static void main(String[] args) {
        for(int i = 0; i < 10; i++) {
            //调用Thread类的currentThread()方法获取当前线程
            //这里的线程是main()方法的方法体,也就是线程执行体           
            System.out.println(Thread.currentThread().getName()+ " " + i);
            if(i == 5) {
                //创建并启动第一个线程
                new FirstThread().start();
                //创建并启动第二个线程
                new FirstThread().start();
            }
        }
    }
}
2.2、实现Runnable接口创建线程类

实现Runnable接口创建线程类
1、定义Runnable接口的实现类,并重写该接口的run()方法,该方法就是线程执行体
2、创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该对象才是真正的线程对象(Thread中的构造方法,详细请看api)
3、调用线程对象的start()方法来启动该线程

package usethread;

public class SecondThread implements Runnable {
    private int i;
    //重写run()方法,run()方法的方法体就是线程执行体
    public void run() {
        for(; i < 10; i++) {
            //当线程继承Thread类时,直接使用this即可获取当前线程,不能使用this
            System.out.println(Thread.currentThread().getName() +" " + i);
        }
    }
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++) {
            //这里的线程是main()方法的方法体,也就是线程执行体
            System.out.println(Thread.currentThread().getName()+ " " + i);
            if(i == 5) {
                //实例化Runnable接口的实例
                SecondThread st = new SecondThread();
                //通过new(target,name)方法创建新进程
                new Thread(st,"线程1").start();
                //通过new(target,name)方法创建新进程
                new Thread(st,"线程2").start();
            }
        }
    }
}
2.3、使用Callable和Future创建线程类

3、线程的生命周期

在线程的生命周期中,它要经过新建、就绪、运行、阻塞和死亡5中状态。

3.1、新建和就绪状态

当使用new关键字创建了一个线程之后,该线程就处于新建状态,当线程对象调用了start()方法之后,该线程处于就绪状态,处于这个状态的线程并没有开始运行,只是表示该线程可以运行了,至于该线程 何时开始运行,取决于JVM里线程调度器的调度。

package usethread;

public class InvokeRun extends Thread {
    private int i;
    //重写run()方法,run()方法的方法体就是线程执行体
    public void run() {
        for(; i < 10; i++) {
            //直接调用run()方法时,Thread的this.getName()返回的是该对象的名字,而不是线程的名字
            //使用Thread.currentThread().getName()总是获取当前线程的名字
            System.out.println(Thread.currentThread().getName() + " " + i);
            System.out.println(this.getName());
        }
    }
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++) {
            //调用Thread的currentThread()方法获取当前线程
            System.out.println(Thread.currentThread().getName() + " " + i);
            if(i == 5) {
                //直接调用run()方法
                //系统会把线程对象当成普通对象,把run()方法当成普通方法
                //下面两行代码不会启动两个线程,而是依次执行两个run()方法
                new InvokeRun().run();
                new InvokeRun().run();
            }
        }
    }
}

这里写图片描述

3.2、运行和阻塞状态

如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则线程处于运行状态。一个线程不可能一直处于运行状态,线程在运行中需要被中断,目的是使其他进程获得执行的机会。
当发生如下情况时,线程将会进入阻塞状态
1、线程调用sleep()方法主动进图阻塞状态
2、线程调用了一个阻塞式IO方法
3、线程试图获得一个同步监听器,但该线程正被其他线程所持有
4、线程在等待某个通知
5、程序调用了线程的suspend()方法将该线程挂起,易产生死锁
当发生如下情况时,线程将会解除阻塞状态
1、调用sleep()方法的线程经过了指定的时间
2、线程调用的阻塞式IO方法已经返回
3、线程成功地获得了试图取得的同步监听器
4、线程正在等待某个通知时,其他进程发出了一个通知
5、处于挂起状态的线程被调用了resume()恢复方法

3.3、线程死亡

线程会以如下三种方式结束,结束后就处于死亡状态
1、run()或call()方法执行完成,线程正常结束
2、线程抛出一个未不活的Exception或Error
3、直接调用该线程的stop()方法结束线程,易导致死锁

package usethread;

public class StartDead extends Thread {
    private int i;
    //重写run()方法,run()方法的方法体就是线程执行体
    public void run() {
        for(; i < 10; i++) {
            System.out.println(this.getName() + " " + i);
        }
    }
    public static void main(String[] args) {
        //创建线程对象
        StartDead sd = new StartDead();
        //新建状态的线程
        System.out.println(sd.isAlive());
        for(int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if(i == 2) {
                //启动线程
                sd.start();
                //判断启动后线程的isAlive()值,输出true
                //当线程处于新建,死亡两种状态时,输出false
                System.out.println(sd.isAlive());
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值