多线程初级

多线程

应用场景:多任务执行|多路径执行

常用基本概念

  1. 程序:Java源程序和字节码文件被称为“程序” ( Program ),是一个静态的概念。
  2. 进程:执行中的程序叫做进程(Process),是一个动态的概念。
  3. 线程:线程(thread)是操作系统能够进行运算调度的最小单位。

进程与线程的区别

区别进程线程
根本区别作为资源分配的单位调度和执行的单位
所处环境在操作系统中能同时运行多个任务(程序)在同一应用程序中有多个顺序流同时执行
分配内存系统在运行的时候会为每个进程分配不同的内存区域线程间共享进程的所有资源,每个线程只有有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行
开销每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立运行栈和程序计数器(PC),线程切换的开销小
包含关系没有线程的进程可以看作单线程,如果一个进程拥有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的线程是进程的一部分,所以线程有的时候会被称为是轻量级进程或轻权进程

多线程执行机制:多线程需要多个CPU,即多核。一般工具内的多线程是模拟出来的,只有一个CPU,一次只能执行一条线程,所以快速切换线程,达到伪多线程

线程的创建与开启

1. 继承Thread

继承Thread,并重写run()+start()

public class XxThread extends Thread{
    //run()方法中定义线程体
    @Override
    public static run(){
        for(int i = 1 ; i <= 20 ; i++){
            System.out.println("喝加非...");
        }
    }
    public static void main(String[] args) {
        //创建线程
        XxThread xth = new XxThread();
        //开启线程
        xth.start();
        //主线程
        for(int i = 1;i<=20;i++){
            System.out.println("敲代码...");
        }
    }
}

注意:

  1. 直接使用xth.run(),只是普通的方法调用,并不是线程的开启
  2. 子类继承父类只能单继承
  3. run方法不能抛出异常,而且也没有返回值

2.Runnable接口

实现Runnable接口,重写run()方法 推荐使用,接口可以多实现,类只能单继承

    public static void main(String[] args) {
        //真实角色
        XxThread xth = new XxThread();
        //创建一个线程
        //代理角色
        Thread th = new Thread(xth);
        //开启线程
        th.start();
        for(int i=0;i<=20;i++){
        	System.out.println("敲代码...");
    	}
	}
主方法,其他同上

代理模式,不能直接使用xth调用start,线程开启只能通过Thread的start方法

3.Callable接口 (了解)

juc 下 Callable接口,重写call()
优点:
call方法可以抛出异常可以定义返回值
缺点:

  1. 使用麻烦
  2. 无法为线程重命名

新概念:

​ 线程池:线程池就是首先创建一些线程,它们的集合称为线程池

package com.xxxx.thread01;
/*
 * 简单模拟龟兔赛跑
 * 	兔子每跑十步休息一下 10毫秒
 * 	乌龟正常跑
 *  只要有参赛者跑了100步就结束
 *  分析:
 *      多线程-->参赛者
 *      同一场比赛,多线程之间共享 String winner;
 */
import java.util.concurrent.*;

public class Racer implements Callable<Integer> {
    //胜利者
    private String winner = null;
 
    @Override
    public Integer call() throws InterruptedException {
        //每一个参赛者都要跑100步结束
        for(int step = 1;step <= 100; step++){
            //判断是否为兔子,并且步数是否为10的倍数
            if("pool-1-thread-1".equals(Thread.currentThread().getName()) && step%10==0){
                Thread.sleep(10);
            }
            System.out.println(Thread.currentThread().getName()+"正在跑第"+step+"步");
            Thread.sleep(2);

            //结束的条件判断
            if(checkOver(step)){
                return step;
            }
        }
        return null;
    }

    /**
     * 决定线程是否结束
     * @param step 步数
     * @return 当前线程是否结束执行
     *      true->结束执行
     *      false ->继续执行
     */
    public boolean checkOver(int step){
        //是否已经有人赢了
        if(winner!=null){
            return true;
        }
        //当前线程是否赢了
        if(step==100){
            winner = Thread.currentThread().getName();
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //1.创建1场比赛
        Racer racer = new Racer();
        //2.
        // 1)创建执行服务
        // 固定大小线程池->2
        ExecutorService server = Executors.newFixedThreadPool(2);
        // 2)提交执行
        Future<Integer> f1 =  server.submit(racer);
        Future<Integer> f2 =  server.submit(racer);
         //3) 获取执行结果
        Integer i1 = f1.get();
        Integer i2 = f2.get();

        System.out.println(i1);
        System.out.println(i2);

        //3.比赛
        server.shutdown();
    }
}

线程的状态

新生状态 : new Thread(),new的时候就是一个线程进入新生状态

就绪状态 : start() 一个线程就会进入到就绪状态,进入就绪队列进行等待,可以等待cpu的调度

运行状态 : 当cpu调用调度到就绪队列中的某一个线程,这个线程开始进入运行状态

阻塞状态 : 线程无法正常执行,可以能会进入到阻塞状态

终止状态 : 线程执行完毕

进入阻塞状态:

1.sleep()
2.join()
3.wait()
4.IO等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值